什么';在退出之前,用perl杀死子进程的正确方法是什么?

什么';在退出之前,用perl杀死子进程的正确方法是什么?,perl,fork,irc,poe,Perl,Fork,Irc,Poe,我正在运行一个IRC Bot(),它有两个子进程正在运行,但退出时,它们不会终止。所以在退出之前,我会像这样杀死他们: my $parent=$$; my $proc_table=Proc::ProcessTable->new(); for my $proc (@{$proc_table->table()}) { kill(15, $proc->pid) if ($proc->ppid == $parent); } 它可以工作,但我得到了以下警告: 14045: !

我正在运行一个IRC Bot(),它有两个子进程正在运行,但退出时,它们不会终止。所以在退出之前,我会像这样杀死他们:

my $parent=$$;
my $proc_table=Proc::ProcessTable->new();
for my $proc (@{$proc_table->table()}) {
  kill(15, $proc->pid) if ($proc->ppid == $parent);
}
它可以工作,但我得到了以下警告:

14045: !!! Child process PID:14047 reaped: 14045: !!! Child process PID:14048 reaped: 14045: !!! Your program may not be using sig_child() to reap processes. 14045: !!! In extreme cases, your program can force a system reboot 14045: !!! if this resource leakage is not corrected.
我会关心为什么您的子进程没有正确终止。在“正常”情况下,家长不应该做任何事情(如果您关心结果,可以调用
waitpid
,或者在完成之前停止处理)

这还不是一个很好的答案——您可能需要在子对象中粘贴一些代码。但是有一点建议——从手动调用
fork
的简单程序开始,而不是依赖CPAN模块来为您执行。了解系统如何处理多个流程很重要。当你有了这些,你可以利用一些框架为你处理很多过程


如果您最近没有这样做,您可能也应该通读一遍,并尝试一些示例。

我对您提到的任何模块都不熟悉,但当我在过去编写forking Perl程序时,通常将这一行放在主父进程中就足够了:

$SIG{CHLD} = sub { wait };

这样,当子进程退出并且父进程收到SIGCHLD信号时,它会自动使用
等待
重新获取子进程,从版本0.82开始,
Bot::BasicBot
将在退出时杀死未完成的子进程(由
forkit()
创建)。

我正在挖掘一篇旧文章,但我一直在寻找这个问题的答案,谷歌搜索把这个列为最重要的结果。所以,如果其他人无意中发现了这一点,我是这样做的

分叉之前,设置一个
管道
,以便分叉的流程可以进行通信:

管道PARENTRECEIVE,CHILDSEND

分叉进程,让子进程立即向父进程发送新的进程ID。然后,当您认为子进程被挂起时(通过计时器或SIG),您可以终止子进程:

my $pid = fork();
if ($pid eq 0) {
  #child block
  my $cid = $$;       
  print CHILDSEND "$cid\n";
  <do child stuff which might hang>
}
else {
  #parent block
  my $child_id = <PARENTRECEIVE>;
  chomp $child_id;
  <do parent stuff>
  <if you think child is hung> {
    kill 1, $child_id;
  }
}
my$pid=fork();
如果($pid eq 0){
#子块
我的$cid=$$;
打印CHILDSEND“$cid\n”;
}
否则{
#父块
我的$child_id=;
chomp$child_id;
{
杀死1,$child_id;
}
}

有时我们的web服务器挂起,所以我使用它来检查它是否在合理的时间内仍然响应HTTP GET请求。如果孩子没有在家长的计时器启动之前抓取完URL,它会发出电子邮件警报,说有什么事情发生了。

可能是因为我没有正确终止bot。几天前我问了一个问题。我试过了,但没用。我第一次按Ctrl+C时,它什么也没做。我又做了一次,它在没有杀死子进程的情况下终止了。子进程应该无限期运行(就像运行“tail-F”),除非被杀死。它不会自行终止。您好,如何终止子进程没有问题。警告只是说,当这些进程死亡时,您尚未注册POE回调-您需要使用POE->kernel->sig_child()注册它们。见:
my $pid = fork();
if ($pid eq 0) {
  #child block
  my $cid = $$;       
  print CHILDSEND "$cid\n";
  <do child stuff which might hang>
}
else {
  #parent block
  my $child_id = <PARENTRECEIVE>;
  chomp $child_id;
  <do parent stuff>
  <if you think child is hung> {
    kill 1, $child_id;
  }
}