首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法接收所有的SIGCHLD

无法接收所有的SIGCHLD
EN

Stack Overflow用户
提问于 2018-02-12 15:52:57
回答 1查看 1.3K关注 0票数 2

在下面的代码中,我期望控制台打印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

代码语言:javascript
复制
#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);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-12 16:20:47

SIGCHLD是一个标准信号,这意味着它的多次发生被折叠为一个。Linux内核维护一个标准信号的位集,每个信号一位,并支持精确地排队一个相关的siginfo_t

修正:

代码语言:javascript
复制
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不是其中之一。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48750382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档