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

时间:2013-03-28 21:12:46

标签: c linux process tree kill

我正在尝试编写一个生成子进程的函数,让它运行一段时间然后如果它还没有完成就杀死它:

int sysExecTimeout(const char * exePath, int timeoutSec);

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

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的子进程。

我正在尝试编写sysExecTimeout函数,以便它杀死以pid为根的整个流程树,其中pid是来自pid = fork()的PID

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

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

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

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

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

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

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

有办法吗?我一直在搜索,但我能找到的只是使用ps -ef的黑客,或修改你正在运行的子进程等。

1 个答案:

答案 0 :(得分:10)

在子节点中使用setpgid将其GPID设置为等于其自己的PID。然后父母可以杀死(-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);
    }
}

应该这样做。

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