在下面的代码中,当睡眠时,如果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";
Run Code Online (Sandbox Code Playgroud)
无论我设定多sleep
长时间,一旦发出QUIT
信号sleep
结束并且程序继续.
有没有一种方法可以处理QUIT
而不影响程序的当前运行,sleep
只要它的意图持续下去?
在宝贵的睡眠周围设置一个块,忽略其中的信号
IGNORE_QUIT: {
local $SIG{QUIT} = 'IGNORE';
sleep 10;
};
Run Code Online (Sandbox Code Playgroud)
如果sleep
恰好已经适当地限定了范围,那么您不需要额外的块.
如果还有更多,可以使用包装器
sub sleep_protected {
local $SIG{QUIT} = 'IGNORE';
sleep $_[0];
}
Run Code Online (Sandbox Code Playgroud)
在当地是至关重要的,这样$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;
}
Run Code Online (Sandbox Code Playgroud)
计数器是本地的并返回,但您可以使用全局计数器,声明为our
.或者将它声明为一个state
变量,它会被记住(见功能).
EINTR
如果被信号中断,则中断的调用将返回错误.这可以使用%进行检查!,作为if ($!{EINTR}) {...}
.但是,我不知道sleep
除了信号之外如何合理地中断,因此没有使用它.