2

PerlのCGI::Fastを使用して動作するアプリケーションがあります。

基本的に、コードのメインループは次のとおりです。

while (my $cgi = CGI::Fast->new() ) {
  do_whatever( $cgi );
}

今、私はそれを殺す能力を追加したかったが、現在処理されているリクエストを中断することはなかった。そのために、SIGHUPに処理を追加しました。多かれ少なかれ線に沿って:

my $sighupped = 0;
$SIG{ 'HUP' } = sub { $sighupped = 1; };
while (my $cgi = CGI::Fast->new() ) {
  do_whatever( $cgi );
  exit if $sighupped;
}

これは、「ユーザーの要求を処理している間、プロセスを妨げない」という点で非常に効果的です。ただし、プロセスが新しい要求を待機している場合、最終的に何らかの要求を取得して処理するまで、ため息ベースの出口は実行されません。

これに対する回避策はありますか?リクエストを待っている間にHUP(または他のシグナル、変更可能)がスクリプトに到達した場合に、スクリプトをすぐに終了させるために実現したいこと。

4

2 に答える 2

1

ハンドラーの場所に基づいてSIGnalを再宣言できます。

fast-cgi whileループの外側にいる場合、またはfast-cgiポーリングの内側にいるため、イベントループにない場合は終了します(基本的にデフォルト)。イベントループロジック内にいる場合は、ロジックが終了して終了するのを待ちます。

現時点で編集者が不足していることをお許しください。

$inlogic=0;
$hupreq=0;
SIG{SIGHUP}={ exit unless($inlogic); $hupreq=1;}

while()
{
   $inlogic=1;
   function();
   $inlogic=0;
   exit if($hupreq);
}
于 2009-03-19T20:46:33.017 に答える
1

関数のブロック バージョンとeval関数を使用しalarmて、タイムアウトを に追加できFast::CGIます。以下のコードでは、5 秒のタイムアウトを設定しています。タイムアウトした場合は、ループの最初に戻り、$continueまだゼロに設定されているかどうかを確認します。そうでない場合は、新しいCGI::Fastオブジェクトを開始します。HUPこれは、新しいオブジェクトを待っていた場合、を送信してからコードが停止し始めるまでに最大 5 秒かかることを意味しCGI::Fastます (タイムアウトはループの残りの部分には影響しません)。

my $continue = 1;
$SIG{HUP} = sub { $continue = 0 };
while ($continue) {
    my $cgi;
    eval {
        local $SIG{ALRM} = sub { die "timeout\n" };
        alarm 5; #set an alarm for five seconds
        $cgi = CGI::Fast->new;
        alarm 0; #turn alarm off
    };
    if ($@) {
        next if $@ eq "timeout\n"; #we will see the HUP signal's change now
        #died for a reason other than a timeout, so raise the error
        die $@;
    }
    last unless defined $cgi; #CGI::Fast has asked us to exit
    do_stuff($cgi);
}

#clean up
于 2009-03-20T00:13:10.897 に答える