【发布时间】:2013-08-26 10:35:20
【问题描述】:
我有一个父进程产生多个子进程。我想通过注册SIGCHLD 信号处理程序来了解任何子进程何时退出。
问题是,如果收到另一个SIGCHLD(或任何其他信号),而父进程已经在信号处理程序中,会发生什么?
我可以想到以下结果:
- 信号被忽略
- 信号已排队,将在当前处理程序返回后立即处理
- 当前处理程序依次被中断,就像主程序一样
哪个是正确的?
【问题讨论】:
-
这是个好问题。
我有一个父进程产生多个子进程。我想通过注册SIGCHLD 信号处理程序来了解任何子进程何时退出。
问题是,如果收到另一个SIGCHLD(或任何其他信号),而父进程已经在信号处理程序中,会发生什么?
我可以想到以下结果:
哪个是正确的?
【问题讨论】:
在您的具体示例中(接收到相同的信号),信号在信号处理程序完成后传递(因此要点 #2 是正确的)。但是请注意,您可能会“丢失”信号。
原因是当信号在其处理程序中时,它被阻塞了。阻塞信号设置为待处理,但不排队。术语“待处理”意味着操作系统记住有一个信号等待在下一个机会被传递,而“未排队”意味着它通过在某处设置一个标志来做到这一点,而不是通过准确记录如何许多信号已经到达。
因此,您在处理程序中可能会收到 2 个或 3 个(或 10 个)更多 SIGCHLD,但只能看到一个(因此在某些情况下,要点 #1 可能也是正确的)。
请注意,您可以传递给sigaction 的几个标志可能会影响默认行为,例如SA_NODEFER(防止阻塞信号)和SA_NOCLDWAIT(在某些系统上可能根本不会生成信号)。
当然,如果您收到不同类型的信号,则无法保证它不会中断您的处理程序。因此,最好不要使用非信号安全函数。
【讨论】:
SIGCHLD 的信号处理程序中,其他SIGCHLD 信号要么丢失,要么在处理程序返回后 传递。但是任何其他类型的信号都会中断信号处理程序本身吗?
SIGSEGV)会字面上中断处理程序,但异步信号当然仍然遵循正常规则,即它们在未知但明确定义的时间传递,例如在内核/用户切换时,它们将不是字面上中断处理程序。但是,如果您给它们一个机会,它们很可能会在处理程序运行时交付(因此仅使用 async-signal-safe 函数)。