6

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

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

在函数中,我使用forkandexecl来生成孩子,当超时时,我使用kill(pid, SIGTERM)andkill(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);
    }
}

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

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

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

我无法控制exePath执行的二进制文件/脚本,因此我无法在其中编写自己的父死子逻辑。

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

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

我可以在这里使用该标志:

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

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

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

4

1 回答 1

15

在子进程中使用 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);
    }
}

那应该这样做。

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

于 2013-03-28T21:35:46.797 回答