Perl 如果父级截获SIGINT,请等待子级完成

Perl 如果父级截获SIGINT,请等待子级完成,perl,fork,Perl,Fork,我有一个带有多个子进程的perl脚本(使用fork()创建)。每个孩子睡觉后都会进行一些处理(几个system()调用)。在windows下,当我点击Ctrl+C时,我看到信号被捕获,然后脚本等待子脚本完成,然后退出。我想在linux中复制这种行为(catch sigint,让孩子们完成并退出主脚本/进程) 在杀死父母之前,我如何等待所有孩子完成?是否可以退出主脚本/杀死父脚本,但让子脚本在后台完成 我发现,似乎SIGINT被传播到子进程(进程组),所以为了避免这种情况,我必须将子进程设置在不同

我有一个带有多个子进程的perl脚本(使用fork()创建)。每个孩子睡觉后都会进行一些处理(几个system()调用)。在windows下,当我点击Ctrl+C时,我看到信号被捕获,然后脚本等待子脚本完成,然后退出。我想在linux中复制这种行为(catch sigint,让孩子们完成并退出主脚本/进程)

在杀死父母之前,我如何等待所有孩子完成?是否可以退出主脚本/杀死父脚本,但让子脚本在后台完成

我发现,似乎SIGINT被传播到子进程(进程组),所以为了避免这种情况,我必须将子进程设置在不同的进程组中

$SIG{'INT'} = sub {
    print "Caught Ctrl+C\n";
    die "Stopping...";
};

++$|;

print "Start\n";
for($i=0; $i < 500; $i++) {
    sleep 3;
    $childPid = fork(); #fork a process
    if($childPid == 0){
        print "Child $i...\n";
        sleep 10;
        system("echo finishing");
        print "Exit child $i\n";
        exit;
    }
}
编辑:

已尝试将子SIGINT处理程序设置为忽略,并按预期工作。在父处理程序中,我执行以下操作:

$SIG{'INT'} = sub {
  print "Caught Ctrl+C by $$\n";
  # while($result != -1){
      # $result = wait();
  #}
    die "Stopping...";
}; 
a)如果包含注释行,脚本将等待子脚本完成,然后退出

b)但是如果我对“等待”行进行注释,我假设它是这样工作的

  • 脚本退出,父进程终止
  • 孩子们继续在后台运行,并在退出前按预期显示“退出孩子”消息
  • 我理解a)案例,但b)案例是如何工作的,请解释为什么这不会生成僵尸进程

    在windows下,当我点击Ctrl+C时,我看到信号被捕获,然后脚本等待子脚本完成,然后退出

    我认为这是psuedo fork实现的一个副作用

    在杀死父母之前,我如何等待所有孩子完成

    最简单的方法是忽略子处理程序中的
    SIGINT
    ,以及父处理程序中的
    wait
    /
    waitpid

    我还尝试将其包含在SIGINT处理块中,但是for循环没有暂停,因此创建了新的子进程,并且父进程没有死亡

    # I used my $parentPid = $$; (before  the for loop) to get the parent pid.
    
    if ($$ = $parentPid){
        foreach $var (@pids) {
            $pid = waitpid($var ,0);
        }  
    
    我想你的意思是
    $==$parentPid
    (比较而不是赋值)。另外,如果你一直在等他们,那么指定你在等哪个孩子也不是很有用

    在windows下,当我点击Ctrl+C时,我看到信号被捕获,然后脚本等待子脚本完成,然后退出

    我认为这是psuedo fork实现的一个副作用

    在杀死父母之前,我如何等待所有孩子完成

    最简单的方法是忽略子处理程序中的
    SIGINT
    ,以及父处理程序中的
    wait
    /
    waitpid

    我还尝试将其包含在SIGINT处理块中,但是for循环没有暂停,因此创建了新的子进程,并且父进程没有死亡

    # I used my $parentPid = $$; (before  the for loop) to get the parent pid.
    
    if ($$ = $parentPid){
        foreach $var (@pids) {
            $pid = waitpid($var ,0);
        }  
    

    我想你的意思是
    $==$parentPid
    (比较而不是赋值)。另外,如果您正在等待所有的孩子,那么指定您正在等待的孩子也不是很有用。

    是的,我的错误是“==”,现在家长退出,我确实收到了“退出孩子”消息,但是,孩子的睡眠过程可能会立即终止,剩下的代码会继续吗?我希望他们按照指示继续睡觉。。。关于等待。。。我应该使用wait()-这会等待所有的子进程吗?是的,信号会中断睡眠,这就是为什么你应该在子进程中设置忽略处理程序(
    $SIG{INT}='ignore'
    )尝试忽略子进程,但我仍然不清楚“等待”的原因。请看编辑你应该一直等到它返回-1是的,我就是这样做的…但是我不明白如果孩子们忽略了SIGINT,家长们没有等待就用“die”退出会发生什么是的,我的错误是“==”,现在家长们退出了,我确实收到了“Exit child”消息,但是马上,也许孩子们的睡眠过程结束了,剩下的代码继续?我希望他们按照指示继续睡觉。。。关于等待。。。我应该使用wait()-这会等待所有的子进程吗?是的,信号会中断睡眠,这就是为什么你应该在子进程中设置忽略处理程序(
    $SIG{INT}='ignore'
    )尝试忽略子进程,但我仍然不清楚“等待”的原因。请看编辑你应该一直等到它返回-1是的,我就是这样做的…但是我不明白如果孩子们忽略了SIGINT,而家长不等待就带着“die”退出会发生什么