杀死进程本身和所有子进程的最佳方法

baj*_*pws 2 parallel-processing perl fork kill child-process

我是新手。我的程序在生命周期内使用 system call 创建了一些子进程fork()。我需要为父进程处理中断信号,并在它的处理程序中杀死在程序运行时创建的所有子进程。
我试过以下代码...

setpgrp(0,0);
$SIG{INT} = \&kill_all;
sub kill_all() {
     print "Going to kill child processes \n";
     kill -9, getpgrp();
}
....
fork()..
....
fork()...
....
fork()
.....
Run Code Online (Sandbox Code Playgroud)

但似乎并非所有进程都被杀死,请提出正确的方法来做到这一点。

Sob*_*que 5

首先 - 不要kill -9。除非您绝对必须这样做,否则这是不好的做法。SIGTERM或者-15更好。

要将事情发送到您的进程组,最简单的方法是(来自perlipchttp : //perldoc.perl.org/perlipc.html#Signals

kill -$$

向负进程 ID 发送信号意味着您将信号发送到整个 Unix 进程组。

或者 -fork返回一个 pid。您可以明确杀死该 pid。

如果您遇到孩子没有响应终止信号而退出的问题,那么最常见的问题是他们进入了不间断状态。

这可能类似于 NFS 挂载上的 IO(或其他不可用的设备 IO)。不幸的是,这是操作系统特定的问题,无法通过 perl 解决。您可以通过运行ps -e v并检查“状态”标志来检查这一点。

state    The state is given by a sequence of characters, for example, "RWNA". The      first character indicates the run state of the process:
D    Marks a process in disk (or other short term, uninterruptible) wait.
I    Marks a process that is idle (sleeping for longer than about 20 seconds).  
L    Marks a process that is waiting to acquire a lock.
R    Marks a runnable process.
S    Marks a process that is sleeping for less than about 20 seconds.
T    Marks a stopped process.
W    Marks an idle interrupt thread.
Z    Marks a dead process (a "zombie").
Run Code Online (Sandbox Code Playgroud)

要么是这样,要么它们已经变成了僵尸进程,正在等待被收割。您可以通过设置$SIG{'CHLD'} = "IGNORE"; But来避免这种情况,正如评论中所述 - 您不应该这样做以及通过 fork-pid 杀死,因为它会创建竞争条件。

你还应该注意 - 如果你配置了一个信号处理程序,然后 fork,那么分叉的孩子也有那个处理程序。您可能需要在子进程中再次删除它。

  • @ThisSuitIsBlackNot,这不是真的。PID 不会被释放,直到使用 `wait`/`waitpid` 收割进程。(请记住,`$SIG{CHLD}='IGNORE';` 是自动收割的。) (4认同)