如果父母拦截了SIGINT,请等待孩子完成 [英] Wait for children to complete if parent intercepts SIGINT

查看:57
本文介绍了如果父母拦截了SIGINT,请等待孩子完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a perl script with multiple child processes (created using fork()). Each child sleeps then does some processing (several system() calls). Under windows when I hit Ctrl+C I see that the signal was caught , then the script waits for the children to complete and after this exits. I want to replicate this behaviour in linux (catch sigint , let the children complete and exit the main script/process ).

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

How do I wait for all children to complete before killing the parent ? Is it possible to exit the main script / kill the parent , but let the children complete in the background ?

我发现子进程接收了父级的SIGINT ,并且似乎SIGINT传播到了孩子(流程组),因此要避免这种情况,我必须将孩子设置在不同的流程组中.

I found Child process receives parent's SIGINT , and it seems SIGINT is propagated to the children (the process group) , so to avoid this I'd have to set the child in a different process group.

$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处理块中,但是for循环没有暂停,因此创建了新的子进程,并且父进程不会死.

I also tried to include this in the SIGINT processing block , but the for loop isn't paused , so new child processes are created and parent doesn't die.

# I used my $parentPid = $$; (before  the for loop) to get the parent pid.

if ($$ = $parentPid){
    foreach $var (@pids) {
        $pid = waitpid($var ,0);
    }  

尝试将子SIGINT处理程序设置为IGNORE,并且按预期工作.在父处理程序中:

Tried setting the child SIGINT handler to IGNORE and it works as expected. In the parent handler I do :

$SIG{'INT'} = sub {
  print "Caught Ctrl+C by $$\n";
  # while($result != -1){
      # $result = wait();
  #}
    die "Stopping...";
}; 

a):如果包含注释行,脚本将等待子级完成然后退出.

a) If include the commented lines the script waits for the children to complete and then exits.

b)但是,如果我评论"wait"行,我认为它的工作原理是这样的

b) But if I comment the "wait" lines I assume it works like this

  1. 脚本退出,父进程终止
  2. 孩子继续在后台运行,并在退出前按预期显示退出孩子"消息.

我了解a)的情况,但b)的情况如何工作,请解释为什么这不生成僵尸进程?

I understand the a) case but how does the b) case work, please explain why doesn't this generate zombie processes ?

推荐答案

在Windows下,当我按Ctrl + C时,我看到信号已捕获,然后脚本等待子项完成,然后退出.

Under windows when I hit Ctrl+C I see that the signal was caught , then the script waits for the children to complete and after this exits.

我认为这是伪叉实现的副作用.

I think this is a side-effect of the psuedo-fork implementation.

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

How do I wait for all children to complete before killing the parent ?

最简单的方法是忽略子代中的SIGINT和父代SIGINT处理程序中的wait/waitpid.

The easiest way is to ignore the SIGINT In the children, and wait/waitpid in the parents SIGINT handler.

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

I also tried to include this in the SIGINT processing block , but the for loop isn't paused , so new child processes are created and parent doesn't die.

我认为您的意思是$$ == $parentPid(比较而不是赋值).另外,如果您仍在等待所有孩子,则指定等待的孩子并不是真正有用.

I think you meant $$ == $parentPid (comparison instead of assignment). Also, it's not really useful to specify which child you're waiting for if you're waiting for all of them anyway.

这篇关于如果父母拦截了SIGINT,请等待孩子完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆