2012-02-10 135 views
2

我有一个进程,并希望当它被杀害时再次启动它。为了达到这个目的,我开始使用prctl(PR_SET_PDEATHSIG, SIGHUP);来捕获其父母的杀戮并重新开始。用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)。

+0

这是疯了。为什么不让父母重新启动孩子,而不是让孩子重新启动父母?整个系统的设置是这样做的,这是微不足道的。 – 2012-02-10 11:53:49

+0

是的,我知道这并没有太大意义。我正在重现我的android应用程序中的进程重启逻辑。 Android启动应用程序(父进程),该进程启动监视父进程健康的监护人(子进程)。 – lstipakov 2012-02-10 11:56:53

+0

@WilliamPursell:不那么疯狂。我的杀毒软件显然做了类似的事情。杀死防病毒程序是一种标准的黑客策略,因此防病毒程序会创建自己的多个实例,并且每个实例都会创建一个监视死亡父代的监护人。杀死-9是不可阻挡的,并且无法检测到 - 在应用程序被杀害时,也就是说。它可以在子进程中检测到。 – 2012-02-10 12:23:57

回答

4

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

解除阻止SIGHUP而在fork()之前的信号处理程序之前exec()父。

+2

sigset_t x; sigemptyset(&x); sigaddset(&x,SIGHUP); sigprocmask(SIG_UNBLOCK,&x,NULL); – lstipakov 2012-02-10 12:22:33

+0

整齐的单行程!) – 2012-02-11 17:44:07