如何防止子进程中的SIGINT传播并杀死父进程? [英] How to prevent SIGINT in child process from propagating to and killing parent process?
问题描述
我最近学习了如何完成整个fork/exec/wait
事情,并最终编写了一些看起来像这样的代码:
I've recently learned how to do the whole fork/exec/wait
thing and ended up writing some code that looked like this stripped down:
#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
外壳程序中退出,那么它也会终止父进程,并且行printf("Hi\n")
永远不会运行.
This works out pretty well, and actually ends up opening the sqlite3
shell, but there's one problem. If you Ctrl + C
out of the sqlite3
shell, then it also terminates the parent process and the line printf("Hi\n")
never runs.
我认为这是因为SIGINT正在传播到父进程,并且在进一步研究之后,我读到SIGINT将终止同一组中的所有进程,这意味着由于父级和子级共享它们所在的同一组都被终止了.
I assumed this was because the SIGINT was being propagating to the parent process, and after looking into it further, I read that a SIGINT will terminate all processes in the same group, meaning since the parent and child share the same group they're both terminated.
我试图通过尝试这样调用setpgid
来解决此问题:
I tried to fix this by doing trying to call setpgid
like so:
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()
调用置于派生位置,将使execlp()
失败.
which ran fine, but that broke the sqlite3
prompt. Moreover Ctrl + C
still killed the parent in this case. I decided to try to narrow it down even more, and then found something weird, and got stumped. Just putting a getpid()
call into the fork will make execlp()
fail.
#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")
的简单内容(尽管这可能与原始问题无关).
and not even just for sqlite3
, but for simple stuff like execlp("ls", "ls")
as well (this might be unrelated to the original question though).
我有点不知所措,我想知道是否有人可以指出我正确的方向.我不太确定该怎么办.
I'm in a bit over my head and I was wondering if anyone could point me in the right direction. I'm not quite sure what to do from here.
- 我正在使用OSX 10.11,并且正在使用clang进行编译.
-
clang --version
:Apple LLVM版本8.0.0(clang-800.0.42.1)
- I'm on OSX 10.11, and am compiling with clang.
clang --version
: Apple LLVM version 8.0.0 (clang-800.0.42.1)
推荐答案
您可以捕获SIGINT或编写信号处理程序. 使用以下代码:
you can either catch the SIGINT or write a signal handler. use the code below:
signal(SIGINT, sig_handler);
void sig_handler(int signo)
{
if (signo == SIGINT)
printf("received SIGINT\n");
}
这篇关于如何防止子进程中的SIGINT传播并杀死父进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!