Tho*_*hle 17 python subprocess sigkill
我有一个程序产生并与CPU重,不稳定的进程通信,而不是由我创建.如果我的应用程序崩溃或被杀死SIGKILL,我希望子进程也被杀死,因此用户不必跟踪它们并手动终止它们.
我知道之前已经讨论过这个主题,但是我已经尝试了所描述的所有方法,并且它们似乎都没有在测试中幸存下来.
我知道它一定是可能的,因为终端一直都在做.如果我在终端中运行某些东西并杀死终端,这些东西总会死掉.
我试过atexit,双叉和ptys.atexit不起作用sigkill; 双叉根本不起作用; 和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)
Run Code Online (Sandbox Code Playgroud)
在上面,创建了子节点并且父节点退出.现在你会期望gnuchess得到一个SIGKILL和死,但它没有.我仍然可以在我的流程管理器中使用100%CPU找到它.
任何人都可以告诉我,我的使用是否有问题prctl?或者您是否知道终端如何设法杀死他们的孩子?
coo*_*o3k 13
我知道这已经好几年了,但我找到了一个解决这个问题的简单(略微hacky)解决方案.在您的父进程中,将所有调用包装在一个非常简单的C程序中,该程序调用prctl()然后执行exec()在Linux上解决了这个问题.我称之为"yeshup":
#include <linux/prctl.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, char **argv) {
if(argc < 2)
return 1;
prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0);
return execvp(argv[1], &argv[1]);
}
Run Code Online (Sandbox Code Playgroud)
从Python(或任何其他语言)生成子进程时,可以运行"yeshup gnuchess [argments]".您会发现,当父进程被终止时,您的所有子进程(应该)都会很好地获得SIGHUP.
这是有效的,因为即使在调用execvp(有效地将yeshup进程"转换"为gnuchess进程,或者你在其中指定的任何命令)之后,Linux也会尊重对prctl的调用(不清楚它),这与fork()不同.
使用prctl的PR_SET_DEATHSIG只能被设置为了这个过程,在呼叫使用prctl -没有任何其他进程,包括此特定进程的孩子.我指向的手册页表达的方式是"在fork()时清除此值" - fork当然,这是其他进程生成的方式(在Linux和任何其他Unix-y操作系统中).
如果您无法控制要在子gnuchess进程中运行的代码(就本例而言,就本例而言),我建议您首先生成一个单独的小"监视器"进程,其中包括跟踪其所有进程兄弟姐妹(你的父进程可以让监视器知道这些兄弟姐妹的pid它们产生它们)并在共同父母死亡时发送它们的杀手信号(监视器需要轮询它,每N秒唤醒你选择的N个检查父项是否还活着; select用来等待来自父项的更多信息,在一个循环中超时N秒.
不是微不足道的,但是这样的系统任务往往不是.终端以不同的方式做到这一点(通过进程组的"控制终端"的概念)但当然,任何一个孩子都可以阻止它(双叉nohup等等).