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 system
,system
实际上忽略了 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 中的当前进程的主要内容,如果未能解决你的问题,请参考以下文章
Python 在 Windows 上发送 SIGINT 信号子进程
SDL/C++ OpenGL 程序,如何阻止 SDL 捕获 SIGINT
Perl,Parallel::ForkManager - 如何实现 fork 超时