ForkManager SIGINT仅在fork中杀死当前进程

时间:2015-07-07 20:00:50

标签: perl parallel-processing fork

我希望在杀死使用ForkManager的perl进程时让所有子进程死掉。在下面的代码中,如果我运行它并在睡眠线运行时点击 ctrl + c ,则睡眠过程被终止,但print行是然后在脚本结束之前同时执行。理想情况下,我想要一个中断立即停止所有执行。我该怎么办?

#!/usr/bin/perl -w
use Parallel::ForkManager;

main {
    my $fork1 = new Parallel::ForkManager(8);
    while (1) {
        $fork1->start and next;
        system("sleep 15s");
        print "Still going!"
        $fork1->finish;
    }
    fork1->wait_all_children;
}

2 个答案:

答案 0 :(得分:6)

根据perldoc systemsystem实际上忽略了SIGINT和SIGQUIT:

  

由于在执行系统期间忽略了SIGINT和SIGQUIT,   如果您希望您的程序在收到这些信号后终止   您需要根据返回值自行安排。

因此,如果您希望在system调用期间SIGINT时您的进程停止执行,则需要自己实现该逻辑:

#!/usr/bin/perl -w
use Parallel::ForkManager;

main {
   my $fork1 = new Parallel::ForkManager(8);
   while (1) {
      $fork1->start and next;
      print "Sleeping...";
      system("sleep 15s") == 0 or exit($?);
      print "Still going!";
      $fork1->finish;
   }
   fork1->wait_all_children;
}

或者更合理的方法是使用Perl内置的sleep

#!/usr/bin/perl -w
use Parallel::ForkManager;

main {
   my $fork1 = new Parallel::ForkManager(8);
   while (1) {
      $fork1->start and next;
      print "Sleeping...";
      sleep 15;
      print "Still going!";
      $fork1->finish;
   }
   fork1->wait_all_children;
}

答案 1 :(得分:2)

首先关闭 - 使用system意味着您可能会发生一些奇怪的事情,因为......然后您就会允许您调用的任何内容来自行处理信号。

这可能是你的问题。

然而,除了perl之外,您可以使用配置信号处理程序 - 如果此过程收到信号该怎么办。默认情况下 - 信号设置为'退出'或者'忽略'。

您可以通过print Dumper \%SIG;

查看当前的内容

然而,我认为最简单的解决方案是设置陷阱SIGINT,然后将kill发送到当前进程组。

  

PROCESS号为零或负数时的kill行为取决于操作系统。例如,在符合POSIX的系统上,零将发出当前进程组的信号,-1将发出所有进程的信号,任何其他负的进程号将作为负信号编号并终止指定的整个进程组。

$SIG{'INT'} = sub { 
    kill ( 'TERM', -$$ );
};