在下面的代码中,我期望控制台打印10个SIGCHLD caught。我已经通过将sa_flags设置为SA_SIGINFO并使用sa_sigaction而不是sa_handler来排队处理SIGCHLD。然而,似乎有些SIGCHLD丢失了。为什么?
我认为fork()可能被SIGCHLD打断,所以我使用SA_RESTART重新启动fork()。我在不同的计算机上运行相同的代码。在我的MacBook上,上面写着[1] 24481 illegal hardware instruction。在另一台Linux计算机上,打印的SIGCHLD caught不足10 SIGCHLD caught。
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#define CHECK(syscall, msg) do { \
if ((syscall) == -1) { \
perror(msg); \
} \
} while(0)
void catch(int signo, siginfo_t *info, void *context) {
if (signo == SIGCHLD) {
printf("SIGCHLD caught\n");
}
}
int main () {
sigset_t new_set;
sigemptyset(&new_set);
sigaddset(&new_set, SIGCHLD);
struct sigaction act;
act.sa_sigaction = catch;
act.sa_mask = new_set;
act.sa_flags = SA_SIGINFO | SA_RESTART;
CHECK(sigaction(SIGCHLD, &act, NULL), "sigaction error");
int pid, i;
for (i = 0; i < 10; i++) {
pid = fork();
if (!pid) return;
}
while (1);
}发布于 2018-02-12 16:20:47
SIGCHLD是一个标准信号,这意味着它的多次发生被折叠为一个。Linux内核维护一个标准信号的位集,每个信号一位,并支持精确地排队一个相关的siginfo_t。
修正:
void catch(int signo, siginfo_t*, void*) {
int status;
pid_t pid;
if(signo == SIGCHLD) {
while((pid = waitpid(-1, &status, WNOHANG)) > 0)
printf("child %u terminated.\n", (unsigned)pid);
}
}还请注意,除非使用SA_NODEFER标志,否则不需要显式阻止您处理的信号,因为它会自动为您阻塞。
而且,在信号处理程序中,只有有限数量的异步信号安全函数(参见man signal-safety)可以使用,printf不是其中之一。
https://stackoverflow.com/questions/48750382
复制相似问题