2012-02-10 101 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