如何使用 C 在 Linux 上以编程方式终止进程树 [英] How to kill a process tree programmatically on Linux using C
问题描述
我正在尝试编写一个生成子进程的函数,让它运行一段时间,然后在它没有完成时终止它:
I am trying to write a function that spawns a child process, lets it run for a certain amount of time and then kills it if it hasn't finished:
int sysExecTimeout(const char * exePath, int timeoutSec);
在函数中,我使用 fork
和 execl
来生成子进程,当它超时时,我使用 kill(pid, SIGTERM)
和 kill(pid, SIGKILL)
2 秒后,确保孩子死亡:
In the function, I use fork
and execl
to spawn the child, and, when it times out, I use kill(pid, SIGTERM)
and kill(pid, SIGKILL)
after 2 seconds, to ensure the child dies:
pid_t pid = fork();
if(pid == 0) {
execl("/bin/sh", "sh", "-c", exePath);
exit(127);
} else if(pid != -1) {
// timeout code
if(timeout) {
kill(pid, SIGTERM);
sleep(2);
kill(pid, SIGKILL);
}
}
我使用的是 Linux,似乎当父进程死亡时,子进程不会自动终止.所以这两个 kill
调用只会杀死 /bin/sh
进程并保持 exePath
命令运行,因为它是 /bin/sh
命令的子进程代码>/bin/sh.
I am using Linux, and it seems that when a parent process dies, the child is not killed automatically. So the two kill
calls will just kill the /bin/sh
process and leave the exePath
command running, since it is a child process of /bin/sh
.
我正在尝试编写 sysExecTimeout
函数,以便它终止以 pid
为根的整个进程树,其中 pid
是来自pid = fork()
I am trying to write the sysExecTimeout
function such that it kills the entire process tree rooted at pid
, where pid
is the PID from pid = fork()
我需要这个,因为 exePath
命令会产生其他命令,这些命令也会产生其他命令,这些命令可能会卡住并消耗资源.
I need this because the exePath
command will spawn other commands, which can also spawn other commands, which could get stuck and consume resources.
我无法控制执行的 exePath
二进制文件/脚本,因此我无法在其中编写自己的 parent-dies-so-kill-the-children 逻辑.
I do not have control over the exePath
binaries/scripts that get executed, so I cannot write my own parent-dies-so-kill-the-children logic in them.
我尝试使用 kill(0, SIGTERM)
,它几乎完成了工作,除了它也杀死了我自己的进程 :)
I tried using kill(0, SIGTERM)
, which almost did the job, except it also killed my own process :)
我想知道是否有一个标志可以在 C 中以编程方式打开,上面写着嘿,伙计,当我死时,带走我所有的孩子并杀死他们,并为他们的孩子递归重复",这样整个过程树就开始了来自该程序的死亡(假设可以遵循 PID/PPID 链).
I am wondering if there is a flag I can turn on programatically in C that says "hey man, when I die, take all my children and kill them, and repeat recursively for their children" such that the entire process tree started from that program dies (assuming the PID/PPID chain can be followed).
我可以在这里使用那个标志:
I could use that flag here:
if(pid == 0) {
turnOnRecursiveDeathFlag();
system(exePath);
//execl("/bin/sh", "sh", "-c", exePath);
exit(127);
}
有没有办法做到这一点?我已经搜索了一段时间,但我能找到的只是使用 ps -ef
的 hack,或者修改您正在运行的子进程等.
Is there a way to do that? I've been searching for a while, but all I can find are hacks using ps -ef
, or modifying the children processes that you are running etc.
推荐答案
在子进程中使用 setpgid 来设置它的 GPID 等于它自己的 PID.然后父级可以 kill(-pid,...) 向整个组发出信号.
Use setpgid in the child to set its GPID equal to its own PID. The parent then can kill(-pid,...) to signal the entire group.
pid_t pid = fork();
if(pid == 0) {
setpgid(0, 0);
execl("/bin/sh", "sh", "-c", exePath);
exit(127);
} else if(pid == -1) {
// timeout code
if(timeout) {
kill(-pid, SIGTERM);
sleep(2);
kill(-pid, SIGKILL);
}
}
应该可以.
还有一件事,当您生成 shell 时,请确保它没有启用作业控制.否则,它将创建自己的进程组.你的/bin/sh -c"没问题.
One more thing, when you spawn a shell, make sure it doesn't enable job control. Otherwise, it will create its own process groups. Your "/bin/sh -c" is fine.
这篇关于如何使用 C 在 Linux 上以编程方式终止进程树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!