我希望在杀死使用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;
}
答案 0 :(得分:6)
根据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;
}
答案 1 :(得分:2)
首先关闭 - 使用system
意味着您可能会发生一些奇怪的事情,因为......然后您就会允许您调用的任何内容来自行处理信号。
这可能是你的问题。
然而,除了perl
之外,您可以使用配置信号处理程序 - 如果此过程收到信号该怎么办。默认情况下 - 信号设置为'退出'或者'忽略'。
您可以通过print Dumper \%SIG;
然而,我认为最简单的解决方案是设置陷阱SIGINT
,然后将kill
发送到当前进程组。
PROCESS号为零或负数时的kill行为取决于操作系统。例如,在符合POSIX的系统上,零将发出当前进程组的信号,-1将发出所有进程的信号,任何其他负的进程号将作为负信号编号并终止指定的整个进程组。
$SIG{'INT'} = sub {
kill ( 'TERM', -$$ );
};