使用SIGHUP重新启动已终止的进程

时间:2012-02-10 11:50:09

标签: c++ linux shell fork signals

我有一个进程,并希望在它被杀死时再次启动它。为了达到这个目的,我启动了一个孩子“监护人”过程,它使用prctl(PR_SET_PDEATHSIG, SIGHUP);来捕获其父母的杀戮并再次启动它。

这是监护人的代码(省略了记录):

void restart (int signal) {
    if (getppid() == 1) {
        if (fork() == 0) {
            execl("./process", 0);
        }
        exit(1);
    }
}

int main() {
    prctl(PR_SET_PDEATHSIG, SIGHUP, NULL, NULL, NULL);

    struct sigaction new_action, old_action;
    new_action.sa_handler = restart;
    sigemptyset (&new_action.sa_mask);
    new_action.sa_flags = 0;

    sigaction (SIGHUP, NULL, &old_action);

    if (old_action.sa_handler != SIG_IGN) {
        sigaction (SIGHUP, &new_action, NULL);
    } 

    while (getppid() != 1) {
        sleep(86400000);
    }
    return 0;
}

父母:

int main() {
    if (fork() == 0) {
        execl("./guardian", 0);
    } 
    while (1) {
        cout << "I am process\n";
        sleep(1);
    }
    return 0;
}

我遇到的问题是它只运行一次。第一次启动流程时输出ps

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1012     13058  0.0  0.3  20244  1932 pts/1    Ss   08:22   0:00 -sh
1012     22084  0.0  0.1  11484  1004 pts/1    S+   11:20   0:00  \_ ./process
1012     22085  0.0  0.1  11484  1000 pts/1    S+   11:20   0:00      \_ [guardian]
1012     12510  0.0  0.3  20784  1712 pts/0    Ss   08:14   0:00 -sh
1012     22088  0.0  0.1  17412  1012 pts/0    R+   11:20   0:00  \_ ps fu

看起来不错。接下来我用kill -9 22084杀死进程。并再次ps输出:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1012     13058  0.0  0.3  20244  1932 pts/1    Ss+  08:22   0:00 -sh
1012     12510  0.0  0.3  20784  1712 pts/0    Ss   08:14   0:00 -sh
1012     22091  0.0  0.1  17412  1012 pts/0    R+   11:21   0:00  \_ ps fu
1012     22089  0.0  0.1  11484   996 pts/1    S    11:20   0:00 [process]
1012     22090  0.0  0.1  11484   996 pts/1    S    11:20   0:00  \_ [guardian]

当我再次杀死进程时kill -9 22089监护人似乎没有获得SIGHUP回调(我从日志中检查过,这里省略了它们)。

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1012     13058  0.0  0.3  20244  1932 pts/1    Ss+  08:22   0:00 -sh
1012     12510  0.0  0.3  20784  1712 pts/0    Rs   08:14   0:00 -sh
1012     22339  0.0  0.1  17412  1008 pts/0    R+   11:27   0:00  \_ ps fu
1012     22090  0.0  0.1  11484   996 pts/1    S    11:20   0:00 [guardian]

我的问题是 - 为什么监护人没有获得SIGHUP?

我怀疑它可能与后台进程组有关 - 当进程重新启动时,它处于后台组(比较ps stat中的S +和S)。

1 个答案:

答案 0 :(得分:4)

在处理SIGHUP的信号处理程序时,看起来SIGHUP被阻止了。 fork()exec()继承了信号掩码,因此你的第二个监护人再也没有收到它。

SIGHUP之前的fork()之后的信号处理程序中取消阻止exec()