在下面的代码中,如果在进入休眠状态时出现QUIT信号,则休眠将立即结束,并执行最后一行代码。
#!/opt/tertio/localperl/bin/perl
use strict;
use warnings;
my $quit = 0;
$SIG{'QUIT'} = sub {
print "Please dont try to take thread dump as i am not java\n";
$quit++;
};
my $sleep = shift || 30;
print "I am going to sleep\n";
sleep($sleep);
print "I woke up so will exit, but someone tried to quit me $quit times\n";
无论我将sleep
设置了多长时间,一旦我发送QUIT
信号sleep
,程序就会结束。
是否有一种方法可以处理QUIT
而又不影响程序的当前运行,从而使sleep
持续到预期的时间?
答案 0 :(得分:5)
围绕那个宝贵的睡眠建立一个障碍,以忽略其中的信号
IGNORE_QUIT: {
local $SIG{QUIT} = 'IGNORE';
sleep 10;
};
如果sleep
恰好已经确定了范围,那么您就不需要多余的块了。
如果还有更多的话可以使用包装器
sub sleep_protected {
local $SIG{QUIT} = 'IGNORE';
sleep $_[0];
}
local非常重要,因此$SIG{QUIT}
不会全局更改,而只能在块内更改。
如果需要信号处理程序(不能仅使用'IGNORE'
),则sleep
确实会被中断,以便处理程序可以运行。所以您需要重新启动通话
sub sleep_protected {
my $sl = $_[0];
my $sigquit;
local $SIG{QUIT} = sub {
say "Got $_[0], but don't do thread dump";
++$sigquit;
};
$sl -= sleep $sl while $sl > 0;
return $sigquit;
}
该计数器是本地计数器,但已返回,但您可以使用全局计数器(由our
声明)。或将其声明为state
变量,并在每次调用时记住该变量(请参见feature)。
如果被信号中断,则中断的呼叫返回错误EINTR
。可以使用%!作为if ($!{EINTR}) {...}
进行检查。但是,我不知道sleep
怎么可以被信号以外的方式合理地打断,所以没有使用它。