我有一个父进程,它生成十个子进程,并使用SIGCHILD处理程序通知子进程何时死亡。 子进程将在它们启动时通知,然后立即退出。
我使用SA_NODEFER标志来防止SIGCHLD信号在太多进入时被丢弃。孩子们都被正确终止并收到了,但是在这个脚本中以及同时通过控制台信号终止两个信号同时发送时间总是显得一体。
#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include void CHLDHandler(int sig) { char child[] = "Child finished!n"; write(1, &child, sizeof(child)); } int main(int argc, char const *argv[]) { struct sigaction sa; sa.sa_handler = CHLDHandler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; sigaction(SIGCHLD,&sa,NULL); for (size_t i = 0; i < 10; i++) { int pid = fork(); if (pid == 0) { int pid = getpid(); printf("I'm a child with pid %d!n", pid); return 0; } } while(1) { wait(NULL); } return 0; }
基本UNIX信号不排队 – 一次只有一个可以挂起(对于给定的线程)。
如果两个子进程有效地同时终止并因此在“相同”时间提供其SIGCHLD,则您的进程将只有一个待处理的信号。
在收到SIGCHLD后wait
循环是一种长期存在的技术,以补偿SIGCHLD可能“丢失”的事实。 将“Child finished! n”通知移动到调用wait
的循环,您将获得准确的计数。
UPDATE
如果你必须在你的处理程序中收获,你可以在处理程序中调用wait
,因为它是异步信号安全的 :
static void CHLDHandler(int sig) { static char child[] = "Child finished!n"; int save_errno = errno; while (waitpid((pid_t)-1, NULL, WNOHANG) > 0) { write(STDERR_FILENO, &child, sizeof(child) - 1); // don't write the terminating NULL } errno = save_errno; }
在这种情况下,我不会设置SA_NODEFER,因为另一个SIGCHLD可能会中断(EINTR) waitpid
或write
调用。
以上就是c/c++开发分享为什么即使设置了SA_NODEFER标志,sigaction处理程序也不处理每个信号?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/550028.html