我有一个带有多个子进程的perl脚本(使用fork()创建)。每个孩子睡觉然后做一些处理(几个系统()调用)。在Windows下,当我按下Ctrl + C时,我看到信号被捕获,然后脚本等待孩子完成并在此退出之后。我想在linux中复制这种行为(捕获sigint,让孩子完成并退出主脚本/进程)。
如何在杀死父母之前等待所有孩子完成?是否可以退出主脚本/杀死父级,但让孩子在后台完成?
我找到Child process receives parent's 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处理块中,但for循环没有暂停,因此创建了新的子进程,父进程不会死。
# I used my $parentPid = $$; (before the for loop) to get the parent pid.
if ($$ = $parentPid){
foreach $var (@pids) {
$pid = waitpid($var ,0);
}
修改
尝试将子SIGINT处理程序设置为IGNORE,它按预期工作。在父处理程序中我做:
$SIG{'INT'} = sub {
print "Caught Ctrl+C by $$\n";
# while($result != -1){
# $result = wait();
#}
die "Stopping...";
};
a)如果包含注释行,脚本会等待孩子完成然后退出。
b)但是,如果我评论“等待”行,我认为它的工作原理如下
我理解a)案例,但b)案例如何运作,请解释为什么这不会产生僵尸进程?
答案 0 :(得分:0)
在Windows下,当我按下Ctrl + C时,我看到信号被捕获,然后脚本等待孩子完成并在此之后退出。
我认为这是psuedo-fork实现的副作用。
如何在杀死父母之前等待所有孩子完成?
最简单的方法是忽略子项中的SIGINT
和父项wait
处理程序中的waitpid
/ SIGINT
。
我也尝试将其包含在SIGINT处理块中,但for循环没有暂停,因此创建了新的子进程并且父进程没有死。
我认为你的意思是$$ == $parentPid
(比较而不是作业)。此外,如果您还等待所有孩子,那么指定您正在等待的孩子并不是真的有用。