分叉后调用信号
“代码清单1”和“代码清单2”有什么区别吗?因为在代码清单 1 中,子进程能够捕获 SIGTERM 信号并顺利退出。但是代码清单 2 在 SIGTERM 信号上突然终止。
我使用的是 Linux 和 C。
代码清单 1
if (signal(SIGTERM, stopChild) == SIG_ERR) {
printf("Could not attach signal handler\n");
return EXIT_FAILURE;
}
pid = fork();
代码清单 2
pid = fork();
if (signal(SIGTERM, stopChild) == SIG_ERR) {
printf("Could not attach signal handler\n");
return EXIT_FAILURE;
}
奇怪的是,在代码清单 2 中,子进程和父进程都设置了信号处理程序SIGTERM。所以,这应该有效。不是吗?
Is there any difference between "code listing 1" and "code listing 2"? Because in Code Listing 1, the child process is able to catch the SIGTERM signal and exit nicely. But code listng 2 is terminating abruptly on SIGTERM signal.
I am using Linux and C.
Code Listing 1
if (signal(SIGTERM, stopChild) == SIG_ERR) {
printf("Could not attach signal handler\n");
return EXIT_FAILURE;
}
pid = fork();
Code Listing 2
pid = fork();
if (signal(SIGTERM, stopChild) == SIG_ERR) {
printf("Could not attach signal handler\n");
return EXIT_FAILURE;
}
The strange part is that in Code Listing 2, both child and parent process sets the signal handler for SIGTERM. So, this is supposed to work. Isn't it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您从父进程发送 SIGTERM,则最终结果取决于进程的调度顺序。
如果首先调度子进程,则一切正常:
但如果首先调度 paren,则子进程可能没有时间设置信号处理程序:
这称为竞争条件,因为最终结果取决于就看谁先跑。
If you are sending the SIGTERM from the parent, the end result depends on the order on which processes get scheduled.
If the child gets scheduled first, everything works:
But if the paren gets scheduled first, the child may have not had time to setup the signal handler:
This is called a race condition, because the end result depends on who gets to run first.
首先,signal()已被弃用,最好使用sigaction() 。我不认为 fork() 有完全消失的危险,因为很多东西都使用它,但 sigaction() 确实提供了一个更好的界面。
您遇到的行为通常是由从线程内调用 fork() 引起的。 POSIX具体解决了这个问题:
这意味着,您不是继承父级整个地址空间的副本,而是仅继承调用线程地址空间的副本,其中不包含您的处理程序。可以想象,您确实(甚至可能无意中)从线程内调用 fork() 。
子进程获取父进程地址空间的副本。与信号的唯一区别是待处理信号,子级将不会收到该信号,因为它获得了初始化为零的信号集。但是,是的,它确实获得了处理程序的副本。
First, signal() is deprecated, it's better to use sigaction(). I don't think fork() is in danger of vanishing altogether since so many things use it, but sigaction() does provide a much nicer interface.
The behavior you are experiencing is commonly caused by calling fork() from within a thread. POSIX addresses this specifically:
This means, rather than inheriting a copy of the parent's entire address space, you inherit only a copy of the calling threads address space, which doesn't contain your handlers. It might be conceivable that you are, indeed (perhaps even unwittingly) calling fork() from within a thread.
A child process gets a carbon copy of the parent's address space. The only difference with signals would be pending signals, which the child will not receive as it gets a signal set initialized to zero. But yes, it does get a copy of the handlers.
嗯,根据 man fork 的说法:
在第一个示例中,信号处理程序将从父进程的上下文复制到分叉的孩子。但我无法解释为什么在第二个示例中在子级中设置信号处理程序会失败。
Well, according to man fork:
In the first example the signal handler will be copied from the context of the parent to the forked child. But I can not explain why in the second example setting the signal handler in the child would fail.