所以我有一个针对SIGCHLD的自定义处理程序和一个wait()函数。在父级向其发送信号SIGUSER2后,该子级将退出。在此示例中,当子级调用“ exit(0)”时,父级将处理SIGCHLD并退出,还是“ wait()”函数可能在处理SIGCHLD信号之前返回?
#include<stdio.h>
#include<wait.h>
#include<signal.h>
pid_t pid;
int counter = 0;
void handler1(int sig)
{
printf("A\n");
kill(pid, SIGUSER2);
}
void handler2(int sig)
{
printf("B\n");
exit(0);
}
int main()
{
signal(SIGUSR1, handler1);
signal(SIGCHLD, handler2);
if ((pid = fork()) == 0)
{
signal(SIGUSR1, handler2);
kill(getppid(), SIGUSR1);
while(1) ;
}
if ((p = wait(&status)) > 0)
{
printf("wait returned before SIGCHLD");
}
}
答案 0 :(得分:1)
从wait
的联机帮助页中,它可以获取EINTR
:
未设置EINTR WNOHANG并捕获到畅通的信号或SIGCHLD
因此,如果SIGCHLD
有一个处理程序,而您在wait
中,则信号将首先发生 。
这才有意义。因为SIGCHLD
处理程序是执行wait
来收割孩子的自由。某些程序在基线代码中不不执行wait
,但依赖处理程序。
正如其他人所提到的,不要在处理程序中执行printf
[它执行malloc
并且所有赌注都关闭了]。但是,执行wait
是可以的[在处理程序中可以进行某些系统调用。
您的程序有几个问题。我重构了一下。它显示SIGCHLD
在wait
完成之前(如手册页所示)。
请注意,这是一项相当不错的测试,但是确定的测试可能涉及到一个第三过程,该过程必须杀死原始孩子(小睡后 )以允许家长输入wait
。
也就是说,在主流程进入kill
之后,wait
将会发生(在流程3中)。
我没有这样做,所以这是更简单的版本:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
pid_t pid;
volatile int gotsig = 0;
void
handler_cld(int sig)
{
gotsig = 1;
}
void
handler_usr1(int sig)
{
exit(0);
}
int
main()
{
int status;
signal(SIGUSR1, handler_usr1);
signal(SIGCHLD, handler_cld);
pid = fork();
if (pid == 0) {
while (1);
}
// kill the child
kill(pid,SIGUSR1);
if ((pid = wait(&status)) > 0) {
printf("wait returned %s SIGCHLD\n",gotsig ? "after" : "before");
}
return 0;
}
更新:
这是更复杂的版本,它使用单独的“杀手”过程来杀死孩子,但结果是相同的:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
volatile int gotsig = 0;
void
handler_cld(int sig)
{
gotsig += 1;
}
void
handler_usr1(int sig)
{
exit(0);
}
int
main()
{
int status;
signal(SIGUSR1, handler_usr1);
signal(SIGCHLD, handler_cld);
pid_t pidcld = fork();
if (pidcld == 0) {
while (1);
}
pid_t pidkill = fork();
if (pidkill == 0) {
sleep(1);
// kill the child
kill(pidcld,SIGUSR1);
sleep(3);
exit(0);
}
pid_t pidany;
// wait for child
if ((pidany = waitpid(pidcld,&status,0)) > 0) {
printf("wait on child returned %s SIGCHLD\n",
gotsig ? "after" : "before");
}
// wait for child
if ((pidany = waitpid(pidkill,&status,0)) > 0) {
printf("wait on killer returned %s SIGCHLD\n",
gotsig ? "after" : "before");
}
return 0;
}