我在perl中使用Thread::Pool
模块来并行化一些perl代码。这个过程需要一段时间,偶尔我会使用SIGINT
从命令行中删除它。这样做会导致程序突然结束,正如我预期的那样。这会留下一些凌乱的临时文件,所以我想安装一个信号处理程序。我这样做了:
sub INT_Handler{
#clean up code
exit(1);
}
$SIG{'INT'} = 'INT_handler';
在创建线程池并启动线程之前。现在,当我发送SIGINT
时,正在运行的worker threads会死,但是池会立即启动另一组工作程序来处理下一组作业并继续运行。为什么在信号处理程序中退出的调用不会退出主线程?我需要什么来阻止该进程运行?
编辑以回应暴徒的评论
**进一步编辑**
这是我写的一个例子。
use Thread::Pool;
sub INT_handler{
print "Handler\n";
exit(1);
}
$SIG{'INT'}='INT_handler';
sub f{
print "Started a thread " . rand(10000) . "\n";
sleep(10);
}
my $pool;
my $submit = \&f;
if (0){
$pool = Thread::Pool->new({do=>'f', workers=>5});
$submit = sub{ $pool->job; }
}
for (my $i = 0; $i < 100; $i++){ $submit->(); }
$pool->shutdown if defined $pool;
0
,我看到了预期的结果
h:57 Sep 15 16:15:19> perl tp.pl
Started a thread 3224.83224635111
Handler
但是1
发生了这种情况
h:57 Sep 15 16:14:56> perl tp.pl
Started a thread 5034.63673711853
Started a thread 9300.99967009486
Started a thread 1394.45532885478
Started a thread 3356.0428193687
Started a thread 1424.4741558014
等,并且没有输入处理程序并且该过程继续运行。我不得不使用SIGINT
以外的信号来杀死进程。如果没有处理程序,两种情况都会在传递SIGINT
时退出。
答案 0 :(得分:4)
这是一个提示而不是一个明确的答案,但看起来你的主线程永远不会处于“安全”状态来运行信号处理程序。当你启用Perl的不安全信号时它会工作:
PERL_SIGNALS=unsafe perl tp.pl
有关安全和不安全信号的更多信息,请参阅perlipc - 也许它会引导您朝着正确的方向实施安全信号(可能应该如此)。
Perl::Unsafe::Signals
的这种解决方法也可以使处理程序按预期工作
use Perl::Unsafe::Signals;
...
UNSAFE_SIGNALS {
$pool->shutdown if defined $pool;
};
很明显,Perl的安全信令机制正在干扰处理器上的信号。我想知道是否可以通过在UNSAFE_SIGNALS { ... }
内放置一个Thread::Pool::shutdown
块来解决这个问题。无论哪种方式,我都会file a bug report关于此事。