繁体   English   中英

Perl将SIGINT转发给分叉的子进程

[英]Perl forward SIGINT to forked child process

因此,我试图创建一个派生一个工人并等待其完成的Perl程序。 在我的实际用例中,我需要派遣许多工人并等待他们全部,因此我想我将与一个工人一起测试一个测试用例。 我在这里担心的是,当我在终端中运行该程序时,发送^C不会杀死父进程,即使信号处理程序似乎应该获得子进程并导致父进程正常退出。 我正在尝试使用waitpid使父进程保持活动状态,以便它可以接收信号并将它们传递给子进程,但是父进程似乎完全忽略了^C

use strict;
use warnings FATAL => 'all';
use POSIX ":sys_wait_h";

my $cpid;

sub reap_children_and_exit {
    defined $cpid and kill 'HUP', $cpid;
    exit 0;
}

$SIG{INT} = \&reap_children_and_exit;

my $child_text = <<'EOF';
perl -e 'while (1) { printf "%s\n", rand() }'
EOF

$cpid = fork;
if ($cpid == 0) {
    exec($child_text)
}

waitpid($cpid, WNOHANG);

我正在尝试使用waitpid使父母活着

您告诉waitpid立即返回。 WNOHANG更改为0

如果您不需要自己全部实现并且可以使用一个模块,那么我建议您: https : //metacpan.org/pod/Parallel :: Prefork该模块为您轻松地封装了所有工人/孩子的创建和管理,此外,它可以节省内存使用量。

如果您打算创建一个守护程序,那么还有一个可以管理派生的守护程序: https ://metacpan.org/pod/Daemon:: Control

或尝试以下解决方案:

use strict;
use warnings FATAL => 'all';
use feature 'say';
use POSIX ":sys_wait_h";

BEGIN {
    sub reap_children_and_exit {
        my $signame = shift;
        my $pid = shift;
        defined $pid and kill $signame, $pid;
        say "$pid => Received '$signame' !";
        exit 0;
    }
    $SIG{INT} = \&reap_children_and_exit;
}

my %children;

$SIG{CHLD} = sub {
    # don't change $! and $? outside handler
    local ($!, $?);
    while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) {
        delete $children{$pid};
        reap_children_and_exit('HUP', $pid);
    }
};

my $child_text = <<'EOF';
perl -e 'while (1) { printf "%s\n", rand(); sleep 1; }'
EOF

while (1) {
    my $pid = fork();
    die "Cannot fork" unless defined $pid;
    say "I'm the PID $pid";
    if ($pid == 0) {
        say q{I'm the parent};
        exit 0;
    } else {
        $children{$pid} = 1;
        system($child_text);
    }
}

希望对您有帮助。 最好的祝福!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM