【发布时间】:2011-10-29 10:29:17
【问题描述】:
我在 posix 进程方面遇到问题,无法解决。
我有一个派生多个子进程的进程(进程树可能很复杂,而不仅仅是一层)。它还跟踪活跃儿童的 PID。在某些时候,父母会收到一个信号(比如说 SIGINT)。
在 SIGINT 的信号处理程序中,它遍历子进程列表并向它们发送相同的信号以防止僵尸。现在问题来了
- 如果父进程没有 waitpid() 停止子进程,则信号似乎永远不会发送(僵尸继续运行)
- 如果父母在每次 kill() 发送给孩子后都等待,它只是挂在那里,孩子似乎忽略了信号
父子节点具有相同的信号处理程序,因为它是在分叉之前安装的。 这是一个伪代码。
signal_handler( signal )
foreach child in children
kill( child, signal )
waitpid( child, status )
// Releasing system resources, etc.
clean_up()
// Restore signal handlers.
set_signal_handlers_to_default()
// Send back the expected "I exited after XY signal" to the parent by
// executing the default signal handler again.
kill( getpid(), signal )
有了这个实现,执行会在 waitpid 上停止。如果我删除 waitpid,孩子们会继续运行。
我的猜测是,除非信号处理程序已经结束,否则从它发送的信号不会分派给孩子。但是,如果我省略了等待,为什么他们不派出呢?
提前非常感谢!
【问题讨论】:
-
看起来孩子们被困在信号处理程序中。
children在孩子们身上有什么价值?cleanup是做什么的? -
childenin children 如果是叶子则为空(否则包含其子进程)。就在分叉之后,我清空了孩子中的这个数组。为了调试,cleanup是 viod(空)。 -
出于好奇,SIGCHLD的性格是什么?
-
不管信号处理程序如何,在同一代码执行中还有另一个等待,它等待所有子进程停止(不仅仅是一个 pid),但没有设置 SIGCHLD 的信号处理程序。跨度>
-
如果到目前为止还没有人提出令人信服的解释——我当然没有——你可能会发布一些代码。您能否将代码缩减为重现问题的最小样本?