请考虑以下fork()
/SIGCHLD
伪代码。
// main program excerpt
for (;;) {
if ( is_time_to_make_babies ) {
pid = fork();
if (pid == -1) {
/* fail */
} else if (pid == 0) {
/* child stuff */
print "child started"
exit
} else {
/* parent stuff */
print "parent forked new child ", pid
children.add(pid);
}
}
}
// SIGCHLD handler
sigchld_handler(signo) {
while ( (pid = wait(status, WNOHANG)) > 0 ) {
print "parent caught SIGCHLD from ", pid
children.remove(pid);
}
}
在上面的例子中有一个竞争条件。" "有可能/* child stuff */
在 " " 开始之前完成,/* parent stuff */
这可能导致孩子的 pid 在退出后被添加到孩子列表中,并且永远不会被删除。当应用程序关闭时,父母将无休止地等待已经完成的孩子完成。
我能想到的一种解决方案是有两个列表:started_children
和finished_children
. 我会添加到started_children
我现在添加到的同一个地方children
。但是在信号处理程序中,不是从children
我删除,而是添加到finished_children
. 当应用程序关闭时,父母可以简单地等到started_children
和之间的差异finished_children
为零。
我能想到的另一个可能的解决方案是使用共享内存,例如共享父母的孩子列表并让孩子.add
和.remove
他们自己?但我对这方面了解不多。
编辑:另一个可能的解决方案,这是我首先想到的,就是sleep(1)
在开头添加一个,/* child stuff */
但这对我来说很有趣,这就是我忽略它的原因。我什至不确定这是 100% 修复。
那么,您将如何纠正这种竞争条件?如果有一个完善的推荐模式,请告诉我!
谢谢。