Net::Server その2(長い処理をしたい)
前回(http://d.hatena.ne.jp/dayflower/20060908/1157706291)の続きです。やろうと思っていることは,
といったクラサバです。前回までに 1. と 2. の一部をやりました(コマンドを与えるというより接続しただけですが)。で,今日やりたいのは 3. のあたりの一部です。
時間がかかる処理ということで sleep をかましてみます。前回の process_request のとこで,
sub process_request { my ($self) = @_; warn 'accepted'; eval { my ($in, $out, $err); IPC::Run::run( [qw( /bin/date )], \$in, \$out, \$err, IPC::Run::timeout(10) ) or die $?; print STDOUT $out, "\n"; }; croak $@ if $@; sleep 5; warn 'bye bye'; }
croak 〜 warn の間に sleep をいれる。するとクライアントから接続すると 5 秒後に日付を出して終了します(当たり前)。そうではなくて,クライアントから接続してすぐに終了して欲しいのです。
では,ソケットを close するとクライアントはすぐに終了してくれるのか。
...(略)... close *STDIN; close *STDOUT; sleep 5; warn 'bye bye'; }
と変えて接続してみましたが,駄目(日付がでて5秒後に接続が切れる)。fork して子プロセスに分離してみたりしましたがやはり駄目でした。
Net::Server の sub post_process_request をみてみると,STDIN 等を close した後に $self->{server}->{client} なるハンドルを close しています。こちらがソケット本体でしたか。
このハンドルをじかに触るのもなんなので,考え方を変えて,
sub process_request { 前回と同じ } sub post_process_request { my $self = shift; $self->SUPER::post_process_request; sleep 5; warn 'bye bye'; }
post_process_request をオーバーライドして解決してみました。
すると見事に client から接続するとすぐにコネクションが切れ,5 秒後にサーバログに「bye bye」と出力されました。
本当はこのままでは駄目なのです。Net::Server の run_client_connection を見るとわかりますが,allow_deny によって deny だった場合にも最後に post_process_request に至るのでよろしくないのです。でもこれでとりあえず道筋は立ちました,ということで。
(ここまで書いておきながら,fork して子プロセスの先頭で $self->post_process_request を呼び,最後に exit を呼ぶほうが本筋な気がしてきました)