螺纹perl和信号处理程序

时间:2011-09-15 18:17:34

标签: multithreading perl signal-handling

我在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时退出。

1 个答案:

答案 0 :(得分:4)

这是一个提示而不是一个明确的答案,但看起来你的主线程永远不会处于“安全”状态来运行信号处理程序。当你启用Perl的不安全信号时它会工作:

PERL_SIGNALS=unsafe perl tp.pl

有关安全和不安全信号的更多信息,请参阅perlipc - 也许它会引导您朝着正确的方向实施安全信号(可能应该如此)。


(由暴徒更新)基于Michal最初的见解,使用Perl::Unsafe::Signals的这种解决方法也可以使处理程序按预期工作

use Perl::Unsafe::Signals;
...
UNSAFE_SIGNALS {
    $pool->shutdown if defined $pool;
};

很明显,Perl的安全信令机制正在干扰处理器上的信号。我想知道是否可以通过在UNSAFE_SIGNALS { ... }内放置一个Thread::Pool::shutdown块来解决这个问题。无论哪种方式,我都会file a bug report关于此事。