我有一个程序生成和通信与CPU重,不稳定的进程,不是我创建的。如果我的应用程序崩溃或被SIGKILL
杀死,我希望子进程也被杀死,这样用户就不必跟踪它们并手动杀死它们。
我知道这个话题以前就有过,但我尝试过所有描述的方法,但似乎没有一种方法能经得起考验。
我知道这一定是可能的,因为终端机总是这样。如果我在终端上运行某个东西,然后杀死终端,这些东西总会死掉。
我试过atexit
、双叉和ptys
。atexit
对sigkill
不起作用;double fork根本不起作用;而且ptys
我还没有找到使用python的方法。
今天,我发现了prctl(PR_SET_PDEATHSIG, SIGKILL)
,这应该是当父进程死亡时,子进程命令杀死自己的一种方式。
我试着把它和popen
一起使用,但它看起来一点效果都没有:
import ctypes, subprocess
libc = ctypes.CDLL('/lib/libc.so.6')
PR_SET_PDEATHSIG = 1; TERM = 15
implant_bomb = lambda: libc.prctl(PR_SET_PDEATHSIG, TERM)
subprocess.Popen(['gnuchess'], preexec_fn=implant_bomb)
在上面,创建子对象,父对象退出。现在,您可能希望gnuchess
收到SIGKILL
并死亡,但它没有。我仍然可以在使用100%CPU的进程管理器中找到它。
有人能告诉我我使用prctl
有什么问题吗?,
或者你知道终端是如何杀死他们的孩子的吗?
事实上,我发现你最初的方法对我来说很好——下面是我测试过的正确的代码示例:
回声.py
父进程py
我知道已经很多年了,但我找到了解决这个问题的一个简单(有点老套)的方法。在父进程中,将所有调用包装在一个非常简单的C程序中,该程序调用prctl(),然后调用exec()来解决Linux上的这个问题。我称之为“叶树”:
当从Python(或任何其他语言)生成子进程时,可以运行“yeshup gnuchess[argments]”。您会发现,当父进程被终止时,应该很好地放弃所有子进程。
这是因为Linux将接受对prctl的调用(不清除它),即使在调用execvp之后(它有效地将yeshup进程“转换”为gnuchess进程,或在那里指定的任何命令),这与fork()不同。
prctl的
PR_SET_DEATHSIG
只能设置为调用prctl的进程,而不能设置为任何其他进程,包括此特定进程的子进程。我所指向的手册页表示这一点的方式是“这个值在fork()上被清除”-fork
,当然,这是其他进程(在Linux和任何其他Unix-y操作系统中)的派生方式。如果您无法控制要在子流程中运行的代码(实际上,对于您的
gnuchess
示例来说,就是这样的情况),我建议您首先生成一个单独的小“monitor”进程,该进程的作用是跟踪其所有兄弟进程(父进程在生成兄弟进程时可以让monitor知道这些兄弟进程的pid),并在常见父进程死亡时向它们发送致命信号(monitor需要对此进行轮询,在您的选择检查父节点是否仍然存在;使用select
在循环中等待来自父节点的更多信息,超时时间为N秒)。不是微不足道的,但是这样的系统任务通常不是这样的。终端做它的方式不同(通过一个“控制终端”的概念为一个进程组),但当然它是微不足道的任何孩子阻止(双叉,
nohup
,等等)。相关问题 更多 >
编程相关推荐