![当 OS X 上的 Python 进程被终止时,为什么它不会终止子进程?](https://linux22.com/image/1228710/%E5%BD%93%20OS%20X%20%E4%B8%8A%E7%9A%84%20Python%20%E8%BF%9B%E7%A8%8B%E8%A2%AB%E7%BB%88%E6%AD%A2%E6%97%B6%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E5%AE%83%E4%B8%8D%E4%BC%9A%E7%BB%88%E6%AD%A2%E5%AD%90%E8%BF%9B%E7%A8%8B%EF%BC%9F.png)
不久前,当我将 Python 脚本从 Linux 迁移到 OS X 时,我发现一些变化让我感到非常困惑...
在 Linux 上,如果 Python 脚本调用了 os.system(),并且调用进程被终止,那么被调用的进程也会同时被终止。
然而,在 OS X 上,如果主进程被终止,它启动的任何东西都会被留下。
我可以在 OS X/Python 中的某个地方改变这种行为吗?
这给我们的渲染农场带来了问题,虽然可以从管理 GUI 中终止进程,但顶级进程实际上只是一个包装器,因此,虽然渲染农场管理可能认为进程已经消失并且机器被释放以执行另一项任务,但实际的处理器密集型任务仍在运行,这可能导致严重的阻塞。
我知道我可以编写更多逻辑来捕获终止信号并将其传递给子进程,但我希望它可以在较低级别启用。
答案1
在 Linux 上,当你杀死一个父级时,子级会收到一个信号这通常会将其杀死,除非它本来要作为守护进程继续存在,在这种情况下它将捕获 sighup。(我认为这就是为什么人们通常使用 SIGHUP 来告诉守护进程刷新自身,因为它总是被方便地捕获)。
在 Mac OS XI 上找不到文档,但似乎没有发送 SIGHUP。因此,子进程成为孤儿进程,其新父进程是祖父进程。
处理这种情况的方法是向父进程的进程组发送终止信号,而不是父进程本身。这将同时杀死所有子进程和孙进程,但有一个警告。如果任何子进程执行 setpgrp() 或 setsid(),则它将脱离进程组成员身份。它不会将终止信号发送到其旧进程组。通常无需担心后者,因为当用于实现该目的时通常是故意的。