如何使用 C 在 Linux 上以编程方式终止进程树

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15692275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 22:35:51  来源:igfitidea点击:

How to kill a process tree programmatically on Linux using C

clinuxprocesstreekill

提问by Alin Tomescu

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);

In the function, I use forkand execlto 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:

在函数中,我使用forkandexecl来生成孩子,当它超时时,我使用kill(pid, SIGTERM)and kill(pid, SIGKILL)2 秒后,以确保孩子死亡:

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);
    }
}

I am using Linux, and it seems that when a parent process dies, the child is not killed automatically. So the two killcalls will just kill the /bin/shprocess and leave the exePathcommand running, since it is a child process of /bin/sh.

我正在使用 Linux,似乎当父进程死亡时,子进程不会自动终止。所以这两个kill调用只会终止/bin/sh进程并保持exePath命令运行,因为它是/bin/sh.

I am trying to write the sysExecTimeoutfunction such that it kills the entire process tree rooted at pid, where pidis the PID from pid = fork()

我正在尝试编写sysExecTimeout函数,以便它杀死以 为根的整个进程树pidpidPID 来自何处pid = fork()

I need this because the exePathcommand will spawn other commands, which can also spawn other commands, which could get stuck and consume resources.

我需要这个,因为该exePath命令会产生其他命令,这些命令也可能产生其他命令,这些命令可能会卡住并消耗资源。

I do not have control over the exePathbinaries/scripts that get executed, so I cannot write my own parent-dies-so-kill-the-children logic in them.

我无法控制exePath执行的二进制文件/脚本,因此我无法在其中编写自己的 parent-dies-so-kill-the-children 逻辑。

I tried using kill(0, SIGTERM), which almost did the job, except it also killed my own process :)

我尝试使用kill(0, SIGTERM),它几乎完成了工作,除了它也杀死了我自己的进程:)

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).

我想知道是否有一个标志可以在 C 中以编程方式打开,上面写着“嘿,伙计,当我死时,带走我所有的孩子并杀死他们,并为他们的孩子递归重复”,这样整个流程树就从该程序开始模具(假设可以遵循 PID/PPID 链)。

I could use that flag here:

我可以在这里使用那个标志:

if(pid == 0) {
    turnOnRecursiveDeathFlag();

    system(exePath);
    //execl("/bin/sh", "sh", "-c", exePath);
    exit(127);
}

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.

有没有办法做到这一点?我已经搜索了一段时间,但我能找到的只是使用 hackps -ef或修改您正在运行的子进程等。

采纳答案by DoxyLover

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.

在子进程中使用 setpgid 将其 GPID 设置为等于其自己的 PID。然后父级可以 kill(-pid,...) 向整个组发出信号。

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);
    }
}

That should do it.

那应该这样做。

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.

还有一件事,当你生成一个 shell 时,确保它没有启用作业控制。否则,它将创建自己的进程组。你的“/bin/sh -c”很好。