2012-02-10 3 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?

Я подозреваю, что у него может быть что-то с фоновой группой процессов - когда процесс перезапускается, он находится в фоновом режиме (сравните S + и S в ps stat).

+0

Это безумие. Вместо того, чтобы ребенок перезапускал родителя, почему бы просто не перезапустить родительский родитель? Вся система настроена так, что это тривиально. –

+0

Да, я знаю, это не имеет особого смысла. Я воспроизвожу логику перезапуска процесса, которая у меня есть в приложении для Android. Android запускает приложение (родительский процесс), и этот процесс запускает опекун (дочерний процесс), который контролирует здоровье родителя. – lstipakov

+0

@WilliamPursell: Не очень сумасшедший. Мое антивирусное программное обеспечение, по-видимому, делает что-то очень похожее. Убийство антивирусной программы - это стандартная хакерская уловка, поэтому антивирусная программа создает несколько экземпляров самого себя, и каждый из них создает опекуна, который следит за убитым родителем. Kill -9 является неблокируемым и необнаружимым - в случае уничтожения приложения. Он обнаруживается в дочерних процессах. –

ответ

4

Похоже, что SIGHUP заблокирован, когда вы находитесь в обработчике сигналов SIGHUP. fork() и exec() наследуют сигнальную маску, поэтому ваш второй опекун никогда не получает ее снова.

Разблокировать SIGHUP в то время как в обработчике сигнала после fork() до exec() родитель.

+2

sigset_t x; sigemptyset (&x); sigaddset (& x, SIGHUP); sigprocmask (SIG_UNBLOCK, & x, NULL); – lstipakov

+0

Аккуратный однострочный!) –

Смежные вопросы