perl - 编写一个 Perl 程序,以便 Ctrl-C 杀死所有 fork

标签 perl

我有一个程序,它使用 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

  1. 您可以使用 stty -a 观察终端的 INTRISIG 设置。

    • isig(与 -isig 相对)表示已设置 ISIG 标志。
    • intr = ^C 表示 INTR 字符是 Ctrl-C。

关于perl - 编写一个 Perl 程序,以便 Ctrl-C 杀死所有 fork,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47805467/

相关文章:

Perl 和 NLP,从传记中解析名称

python - Perl 的 FindBin 的 Python 等价物是什么?

perl - 如何控制 Perl 中缓冲区刷新的时间

perl - 如何在不触及未更改文件的情况下替换 Perl 中现有文件中的字符串

html - 如何仅使用 HTML::Table 为数据行设置列类?

perl - 如何使可能挂起的 fork 进程超时?

php - 你如何用正则表达式处理这种条件情况?

regex - Perl 正则表达式多重匹配

perl - 给定 Perl 中的包名,如何从包中调用子程序?

html - 在 perl 中解析表数据时遇到问题