Как предотвратить SIGINT в дочернем процессе от распространения и уничтожения родительского процесса?

Недавно я узнал, как сделать всю работу fork/exec/wait и в итоге написал код, который выглядел так:

 #include  #include  #include  int main() { pid_t x = fork(); if (x == 0) { execlp("sqlite3", "sqlite3"); printf("exec failed\n"); } else { wait(NULL); printf("Hi\n"); } } 

Это работает очень хорошо, и на самом деле заканчивается открытие оболочки sqlite3 , но есть одна проблема. Если вы Ctrl + C из оболочки sqlite3 , то он также завершает родительский процесс, и строка printf("Hi\n") никогда не запускается.

Я предполагал, что это произошло из-за того, что SIGINT распространялся на родительский процесс, и, изучив его дальше, я прочитал, что SIGINT прекратит все процессы в одной и той же группе, то есть, поскольку родитель и ребенок имеют одну и ту же группу, они оба прекращается.

Я попытался исправить это, пытаясь вызвать setpgid следующим образом:

 int main() { pid_t x = fork(); if (x == 0) { setpgid(getpid(), getpid()); // <-- Added in this line execlp("sqlite3", "sqlite3"); printf("exec failed\n"); } else { wait(NULL); printf("Hi\n"); } } 

который прошел отлично, но это сломало запрос sqlite3 . Кроме того, Ctrl + C все равно убил родителя в этом случае. Я решил попытаться сузить его еще больше, а потом нашел что-то странное и заглох. Простое выполнение getpid() в fork приведет к getpid() execlp() .

 #include  #include  #include  int main() { pid_t x = fork(); if (x == 0) { getpid(); // <--- just adding this in makes it fail execlp("sqlite3", "sqlite3"); printf("exec failed\n"); } else { wait(NULL); printf("Hi\n"); } } 

и даже не для sqlite3 , но для простых вещей, таких как execlp("ls", "ls") (хотя это может быть не связано с исходным вопросом).

Я немного над головой, и мне было интересно, может ли кто-нибудь указать мне в правильном направлении. Я не совсем понимаю, что делать дальше.

  • Я на OSX 10.11, и компилирую с clang.
  • clang --version : Apple LLVM версия 8.0.0 (clang-800.0.42.1)

вы можете либо поймать SIGINT, либо написать обработчик сигнала. используйте следующий код:

 signal(SIGINT, sig_handler); void sig_handler(int signo) { if (signo == SIGINT) printf("received SIGINT\n"); }