Wait for children to complete if parent intercepts SIGINT

北慕城南 提交于 2020-01-07 03:04:28

问题


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 ?

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;
    }
}

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);
    }  

EDIT:

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) If include the commented lines the script waits for the children to complete and then exits.

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

  1. the script exits and the parent process is terminated
  2. the children continue running in the background and display "Exit child" message as expected before exiting.

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


回答1:


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 ?

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

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 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.



来源:https://stackoverflow.com/questions/33518868/wait-for-children-to-complete-if-parent-intercepts-sigint

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!