Ответ 1
Если вы генерируете SIGINT
с помощью Ctrl-c в системе Unix, тогда сигнал отправляется во всю группу процессов .
Вам нужно использовать setpgid или setsid перевести дочерний процесс в другую группу процессов, чтобы он не получал сигналы, генерируемые управляющим терминалом.
[править]
Обязательно внимательно прочитайте раздел ОБОСНОВАНИЕ страницы setpgid
. Немного сложно включить все возможные условия гонки здесь.
Чтобы гарантировать 100%, что SIGINT
не будет доставлен вашему дочернему процессу, вам нужно сделать что-то вроде этого:
#define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ }
/* Block SIGINT. */
sigset_t mask, omask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0);
/* Spawn child. */
pid_t child_pid = fork();
CHECK(child_pid >= 0);
if (child_pid == 0) {
/* Child */
CHECK(setpgid(0, 0) == 0);
execl(...);
abort();
}
/* Parent */
if (setpgid(child_pid, child_pid) < 0 && errno != EACCES)
abort(); /* or whatever */
/* Unblock SIGINT */
CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0);
Строго говоря, каждый из этих шагов необходим. Вы должны заблокировать сигнал, если пользователь нажимает Ctrl-C сразу после вызова fork
. Вы должны вызвать setpgid
в дочернем случае, если execl
произойдет до того, как родитель успеет что-либо сделать. Вы должны вызвать setpgid
в родительском объекте, если родитель запускается, а кто-то нажал Ctrl-C, прежде чем у ребенка будет время что-то сделать.
Последовательность выше неуклюжая, но она справляется с 100% условий гонки.