我的应用程序可以使用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(或其他信号,它可以被更改)在等待请求时到达它,我想实现它以使脚本立即退出。
答案 0 :(得分:1)
您可以根据处理程序的位置重新声明您的SIGnals。
如果你是在循环之外或在快速cgi轮询中进行快速cgi而不是在 事件循环终止(基本上是默认值)。如果你在事件循环逻辑中,则等待逻辑结束并终止。
原谅我目前没有编辑。
$inlogic=0;
$hupreq=0;
SIG{SIGHUP}={ exit unless($inlogic); $hupreq=1;}
while()
{
$inlogic=1;
function();
$inlogic=0;
exit if($hupreq);
}
答案 1 :(得分:1)
您可以使用eval
函数的块版本和alarm
函数向Fast::CGI
添加超时。在下面的代码中,我设置了五秒超时。如果它超时,它将返回到循环的开始,这将检查$continue
是否已被设置为零。如果没有那么我们就开始一个新的CGI::Fast
对象。这意味着,如果代码在等待新的HUP
对象时代码开始停止之前发送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