3

我正在使用Thread::Poolperl 中的模块来并行化一些 perl 代码。这个过程需要一段时间,偶尔我会在命令行中用SIGINT. 正如我所料,这样做会导致程序突然结束。这留下了一些混乱的临时文件,所以我想安装一个信号处理程序。我这样做了:

sub INT_Handler{
    #clean up code
    exit(1);
}
$SIG{'INT'} = 'INT_handler';

在创建线程池和启动线程之前。现在,当我发送 时,正在运行SIGINT工作线程死亡,但池立即启动另一组工作人员来处理下一组作业并继续运行。为什么信号处理程序中的退出调用不退出主线程?我需要什么来阻止进程运行?

编辑回应暴民的评论

** 进一步编辑 **

这是我写的一个例子。

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.

4

1 回答 1

4

这更像是一个提示,而不是一个明确的答案,但您的主线程似乎永远不会处于运行信号处理程序的“安全”状态。当您启用 Perl 的不安全信号时,它确实有效:

PERL_SIGNALS=unsafe perl tp.pl

有关安全和不安全信号的更多信息,请参阅perlipc ——也许它会引导您朝着正确的方向使用安全信号来实现它(因为它可能应该是这样)。


(由 mob 更新)基于 Michal 的原始见解,这种解决方法Perl::Unsafe::Signals还可以让处理程序按您期望的方式工作

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

很明显,Perl 的安全信号机制在信号传递到处理程序的途中会干扰信号。我想知道这是否可以通过UNSAFE_SIGNALS { ... }Thread::Pool::shutdown. 无论哪种方式,我都会提交一份关于此的错误报告。

于 2011-09-16T00:45:30.853 回答