我有一个程序,它使用 Parallel::ForkManager 进行大量 fork 。它的实现方式非常简单:
my $pm = new Parallel::ForkManager($NUM_PROCESSES);
my $j = 0;
while ($j < $NUM_PROCESSES) {
$j++;
my $pid = $pm->start and next;
[application code here]
$pm->finish;
}
$pm->wait_all_children;
这工作正常,但有时运行后,我需要杀死它。按 Ctrl-C 时的行为很奇怪,我认为它一次可能只会杀死一个 fork 。
我是否需要以不同的方式编写代码才能使 Ctrl-C 传播到所有分支?或者也许使用不同的命令?或者我想要的东西是不可能的?
最佳答案
根据 POSIX specification ,当终端 (tty) 在输入中接收到 INTR
字符(通常是 Ctrl-C)并且设置终端的 ISIG
标志时[1] ,它向前台进程组中以该终端为控制终端的所有进程发送 SIGINT
信号。
演示:
use strict;
use warnings;
use feature qw( say );
use Parallel::ForkManager qw( );
my $id = 0;
sub _say { say sprintf "[%s %s %s] %s", $id, $$, getpgrp(), "@_"; }
my $n = 4;
my $wait = 5;
my $new_pgrp = $ARGV[0];
my $pm = Parallel::ForkManager->new($n);
for (1..$n) {
$pm->start() and next;
$id = $_;
_say "Child";
$SIG{INT} = sub { _say "Caught SIGINT in child"; };
if ($new_pgrp) {
setpgrp() or die $!;
_say "Created process group";
}
sleep($wait);
$pm->finish();
}
_say "Parent";
$SIG{INT} = sub { _say "Caught SIGINT in parent"; };
say "Now! (You have $wait seconds to press Ctrl-C)";
sleep($wait);
输出:
$ perl a.pl 0
[1 16590 16587] Child
[2 16591 16587] Child
[3 16592 16587] Child
[0 16587 16587] Parent
[4 16593 16587] Child
Now! (You have 5 seconds to press Ctrl-C)
^C[4 16593 16587] Caught SIGINT in child
[3 16592 16587] Caught SIGINT in child
[2 16591 16587] Caught SIGINT in child
[0 16587 16587] Caught SIGINT in parent
[1 16590 16587] Caught SIGINT in child
如果父进程收到信号,但子进程没有收到信号,那么您的子进程可能正在启动自己的进程组。
$ perl a.pl 1
[1 16766 16763] Child
[1 16766 16766] Created process group
[2 16767 16763] Child
[2 16767 16767] Created process group
[3 16768 16763] Child
[3 16768 16768] Created process group
[0 16763 16763] Parent
[4 16769 16763] Child
Now! (You have 5 seconds to press Ctrl-C)
[4 16769 16769] Created process group
^C[0 16763 16763] Caught SIGINT in parent
您可以使用
stty -a
观察终端的INTR
和ISIG
设置。isig
(与-isig
相对)表示已设置ISIG
标志。intr = ^C
表示INTR
字符是 Ctrl-C。
关于perl - 编写一个 Perl 程序,以便 Ctrl-C 杀死所有 fork,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47805467/