【问题标题】:Threaded perl and signal handlers线程化 perl 和信号处理程序
【发布时间】:2011-11-18 03:07:37
【问题描述】:

我在 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

etc 并且处理程序没有被输入并且进程继续运行。我不得不用SIGINT 以外的信号终止进程。如果没有处理程序,两种情况都会在传递 SIGINT 时简单地退出。

【问题讨论】:

  • 这与the documentation 存在争议:“信号被脚本的主线程(线程 ID = 0)捕获。”你能隔离并发布一些信号似乎被工作线程捕获的代码吗?
  • @mob 好的,所以我一定是误认为信号被工人捕获了。我认为是这种情况,因为我在信号处理程序中明确调用了 exit。然而,我观察到的是正在运行的工作线程和一组新的工作线程正在启​​动。

标签: multithreading perl signal-handling


【解决方案1】:

这更像是一个提示,而不是一个明确的答案,但您的主线程似乎永远不会处于运行信号处理程序的“安全”状态。当您启用 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 的安全信号机制在信号传递给处理程序的途中会干扰信号。我想知道这是否可以通过在Thread::Pool::shutdown 中放置一个UNSAFE_SIGNALS { ... } 块来解决。无论哪种方式,我都会file a bug report 这个。

【讨论】:

  • 我尝试在示例顶部添加$ENV{PERL_SIGNALS} = "unsafe";,但我仍然遇到同样的问题。但是,如果我在运行脚本之前设置环境变量,它确实有效。这是为什么呢?
  • 该变量可能仅在 perl 开始执行您的脚本时才被评估,因此在脚本中设置它为时已晚。
  • 我发现了一个线程here,其中有人抱怨PERL_SIGNALS 的内部设置在5.14 中停止工作,而在那之前他一直很高兴地使用它。我正在使用 5.8.8!尽管如此,我可能会安装Perl::Unsafe::Signals
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 2012-01-24
  • 1970-01-01
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多