如何在后台进程在Perl中终止时通知我?
我写了一个Perl程序,它在子进程中分叉和调用后台程序,并有一个无尽的while循环,它在父进程中执行一些东西。如何在后台进程在Perl中终止时通知我?
$pid = fork();
if (!$pid) {
exec("program args");
} else {
while (1) {
# do something
# needs help: if program terminated, break
}
}
那么,fork
给你的父进程的孩子的PID(你忠实地检索你的代码)。这正是父母可以照顾孩子的原因。
要终止循环时,可以使用kill 0 $pid
来检查孩子是否仍然存在。请参阅perldoc -f kill
。
我猜,EXEC()阻塞,所以程序退出之前不会回来,但我可能是错的:现在,当子进程后台程序终止while循环应该离开了。
-1不,程序之前使用'fork',所以只有一个子进程会使用'exec',这是正确的。 – sleske 2010-02-03 11:56:21
您需要有一个信号处理程序来处理子进程退出时父进程发送的CHLD信号。 (有关Perl中信号处理的更多详细信息,请参见perldoc perlipc
)。
您可以在else循环中执行类似下面的操作来获取子进程。
...
} else {
$SIG{CHLD} = \&reaper
}
# hash to store exit status of child processes
our %child;
sub reaper {
my $x;
while (($x = waitpid(-1,WNOHANG)) >0) {
$child{$x} = $? >> 8;
}
}
或者你可以设置$SIG{CHLD}='IGNORE'
不要担心子进程成为僵尸。
感谢您的建议。我将它与上面的提示结合起来 – 2010-02-03 12:41:01
根据您的应用程序,您可以不时检查孩子是否结束,然后父母可以完成。你可以在WNOHANG中使用posix waitpid()来做一个无阻塞的等待,或者用信号来检查你的孩子是否仍在运行,或者你可以使用管道(当它被关闭时检查)。我个人会使用waitpid()。在perlipc中有很好的例子。
问题是这个过程正在变成僵尸,所以命令仍然返回true。 – 2010-02-03 12:34:43
虽然设定$ SIG {CHLD} ='IGNORE'(请参阅下一个答案) – 2010-02-03 12:40:44