如何防止subprocess中的SIGINT传播并杀死父进程?

我最近学会了如何做整个fork/exec/wait事情,最后写了一些看起来像这样的代码:

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

这工作得很好,实际上最终打开了sqlite3 shell,但是有一个问题。 如果Ctrl + C离开sqlite3 shell,那么它也会终止父进程,并且printf("Hi\n")永远不会运行。

我认为这是因为SIGINT正在传播给父进程,并且在进一步研究之后,我读到SIGINT将终止同一组中的所有进程,这意味着由于父进程和subprocess共享相同的组,终止。

我试图通过尝试调用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中就会使execlp()失败。

 #include <stdio.h> #include <stdlib.h> #include <unistd.h> 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 --version :苹果LLVM版本8.0.0(铛800.0.42.1)

你可以捕获SIGINT或者写一个信号处理程序。 使用下面的代码:

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