【问题标题】:What happens when a signal is received while already in a signal handler?当信号已经在信号处理程序中接收到时会发生什么?
【发布时间】:2013-08-26 10:35:20
【问题描述】:

我有一个父进程产生多个子进程。我想通过注册SIGCHLD 信号处理程序来了解任何子进程何时退出。

问题是,如果收到另一个SIGCHLD(或任何其他信号),而父进程已经在信号处理程序中,会发生什么?

我可以想到以下结果:

  • 信号被忽略
  • 信号已排队,将在当前处理程序返回后立即处理
  • 当前处理程序依次被中断,就像主程序一样

哪个是正确的?

【问题讨论】:

  • 这是个好问题。

标签: linux signals


【解决方案1】:

在您的具体示例中(接收到相同的信号),信号在信号处理程序完成后传递(因此要点 #2 是正确的)。但是请注意,您可能会“丢失”信号。

原因是当信号在其处理程序中时,它被阻塞了。阻塞信号设置为待处理,但不排队。术语“待处理”意味着操作系统记住有一个信号等待在下一个机会被传递,而“未排队”意味着它通过在某处设置一个标志来做到这一点,而不是通过准确记录如何许多信号已经到达。

因此,您在处理程序中可能会收到 2 个或 3 个(或 10 个)更多 SIGCHLD,但只能看到一个(因此在某些情况下,要点 #1 可能也是正确的)。

请注意,您可以传递给sigaction 的几个标志可能会影响默认行为,例如SA_NODEFER(防止阻塞信号)和SA_NOCLDWAIT(在某些系统上可能根本不会生成信号)。

当然,如果您收到不同类型的信号,则无法保证它不会中断您的处理程序。因此,最好不要使用非信号安全函数。

【讨论】:

  • 所以如果我总结一下,在SIGCHLD 的信号处理程序中,其他SIGCHLD 信号要么丢失,要么在处理程序返回后 传递。但是任何其他类型的信号都会中断信号处理程序本身吗?
  • 是的,对于 1 和 2(在处理程序返回之后 最多传递 1 个额外信号)。对于 3,它也是“是”,尽管带有“但是”。同步信号(例如,SIGSEGV)会字面上中断处理程序,但异步信号当然仍然遵循正常规则,即它们在未知但明确定义的时间传递,例如在内核/用户切换时,它们将不是字面上中断处理程序。但是,如果您给它们一个机会,它们很可能会在处理程序运行时交付(因此仅使用 async-signal-safe 函数)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 2019-06-05
  • 2020-02-27
相关资源
最近更新 更多