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;
}

当涉及到“在处理用户请求时不干扰过程”时,它的效果非常好。但是,如果进程正在等待新的请求,那么基于 sighup 的退出将不会被执行,直到它最终得到一些请求并处理它。

有什么解决方法吗?如果 HUP(或其他信号,可以更改)在等待请求时到达它,我想实现它以使脚本立即退出。

4

2 回答 2

1

您可以根据处理程序的位置重新声明您的信号。

如果您在 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对象。这意味着在您发送 aHUP之后,如果代码正在等待一个新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 回答