如何在Python中在父进程退出时杀死子进程?

3

fork_child.py的代码

from subprocess import Popen
child = Popen(["ping", "google.com"], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
out, err = child.communicate()

我在终端窗口中作为以下方式运行 -

$python fork_child.py

如果我在另一个终端窗口中获取fork_child.py的PID并使用SIGTERM杀死它,"ping"不会被杀死。如何确保当fork_child接收到SIGTERM时,ping也被杀死?

你可以为 SIGTERM 安装一个 signal 处理程序来杀死子进程... - Bakuriu
你能给我指一个例子吗? - arc000
请查看以下链接的示例:https://docs.python.org/3.4/library/signal.html#example - user1907906
2个回答

5

当父进程被杀死时,子进程不会自动死亡。只有在以下情况下子进程才会死亡:

  • 父进程转发信号并等待子进程终止
  • 当子进程尝试通过stdio与父进程通信时。这仅在父进程也创建了子进程使用的文件描述符的情况下才起作用。

signals模块包含编写信号处理程序的示例

因此,您需要:

  • 将所有子进程收集到列表中
  • 安装信号处理程序
  • 在处理程序中,遍历所有子进程
  • 对于每个子进程,调用child.terminate(),然后调用child.wait()

必须调用wait()以允许操作系统回收子进程。如果忘记了它,可能会导致僵尸进程。


我不理解这个语句 - “只有在父进程创建了子进程使用的文件描述符时,这才有效”。您能否详细说明一下? - arc000
1
如果父进程被杀死,它的所有资源都会关闭。如果您创建一个子进程并将其stdio描述符连接到父进程的描述符,则子进程仍然可以执行stdio操作 - 到与父进程使用的相同控制台。但是父进程也可以创建管道。如果父进程死亡,则管道的一端关闭。子进程仍然持有另一端。此时,不会发生任何事情。但是下一次,子进程尝试读取/写入这样的管道时,它会收到错误。 - Aaron Digulla

0
在编程中,杀死整个进程树的简单方法是杀死其进程组,即不要运行kill $pid,而是运行以下命令:
$ kill -TERM -$pid

注意:pid被取反。

Shell为每个命令(管道)创建一个新的进程组,因此您不会误杀无辜的旁观者。

如果子进程没有创建自己独立的进程组,则它们都会死亡。

请参见最佳方法杀死所有子进程


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接