2010-02-03 107 views
3

我写了一个Perl程序,它在子进程中分叉和调用后台程序,并有一个无尽的while循环,它在父进程中执行一些东西。如何在后台进程在Perl中终止时通知我?

$pid = fork(); 
if (!$pid) { 
    exec("program args"); 
} else { 
    while (1) { 
     # do something 

     # needs help: if program terminated, break 
    } 
} 

回答

3

那么,fork给你的父进程的孩子的PID(你忠实地检索你的代码)。这正是父母可以照顾孩子的原因。

要终止循环时,可以使用kill 0 $pid来检查孩子是否仍然存在。请参阅perldoc -f kill

+0

问题是这个过程正在变成僵尸,所以命令仍然返回true。 – 2010-02-03 12:34:43

+0

虽然设定$ SIG {CHLD} ='IGNORE'(请参阅下一个答案) – 2010-02-03 12:40:44

-1

我猜,EXEC()阻塞,所以程序退出之前不会回来,但我可能是错的:现在,当子进程后台程序终止while循环应该离开了。

+0

-1不,程序之前使用'fork',所以只有一个子进程会使用'exec',这是正确的。 – sleske 2010-02-03 11:56:21

2

您需要有一个信号处理程序来处理子进程退出时父进程发送的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'不要担心子进程成为僵尸。

+0

感谢您的建议。我将它与上面的提示结合起来 – 2010-02-03 12:41:01

0

根据您的应用程序,您可以不时检查孩子是否结束,然后父母可以完成。你可以在WNOHANG中使用posix waitpid()来做一个无阻塞的等待,或者用信号来检查你的孩子是否仍在运行,或者你可以使用管道(当它被关闭时检查)。我个人会使用waitpid()。在perlipc中有很好的例子。

相关问题