ForkManager SIGINT 只杀死 fork 中的当前进程

Posted

技术标签:

【中文标题】ForkManager SIGINT 只杀死 fork 中的当前进程【英文标题】:ForkManager SIGINT only kills current process in fork 【发布时间】:2015-07-07 20:00:49 【问题描述】:

当我杀死一个使用 ForkManager 的 perl 进程时,我希望所有子进程都死掉。在下面的代码中,如果我运行它并在 sleep 行运行时按 ctrl+c ,则 sleep 进程被终止,但 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;

【问题讨论】:

system 也分叉了一个进程,我想如果你将 system("sleep 15s") 更改为 Perl 的 sleep 15; 你不会看到同样的行为。 【参考方案1】:

根据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;

【讨论】:

太棒了!我没有意识到系统正在拦截 SIGINT。 (而使用 system() 的原因是这只是许多非睡眠系统命令的一个示例......)【参考方案2】:

首先 - 使用system 意味着你可能会发生一些奇怪的事情,因为......然后你允许你调用的任何东西自己处理信号。

这可能是你的问题。

但除此之外,您可以使用 perl 执行的操作是配置信号处理程序 - 如果此进程收到信号时该怎么办。默认情况下 - 信号设置为“退出”或“忽略”。

您可以通过print Dumper \%SIG;查看当前的情况

但是,我认为解决问题的最简单方法是设置一个处理程序来捕获SIGINT,然后将kill 发送到您当前的进程组。

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

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

【讨论】:

以上是关于ForkManager SIGINT 只杀死 fork 中的当前进程的主要内容,如果未能解决你的问题,请参考以下文章

C - 在 SIGINT 上释放分配的内存

Python 在 Windows 上发送 SIGINT 信号子进程

SDL/C++ OpenGL 程序,如何阻止 SDL 捕获 SIGINT

Perl,Parallel::ForkManager - 如何实现 fork 超时

Perl Parallel::ForkManager ,fork 条件改变需要很长时间

有没有办法干净地杀死uvicorn?