当前位置:  开发笔记 > 编程语言 > 正文

避免fork()/ SIGCHLD竞争条件

如何解决《避免fork()/SIGCHLD竞争条件》经验,为你挑选了1个好方法。

请考虑以下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_childrenfinished_children.我将添加到started_children我现在添加到的相同位置children.但在信号处理程序中,而不是从children添加到删除finished_children.当应用程序关闭时,父级可以简单地等到started_children和之间的差异finished_children为零.

我能想到的另一个可能的解决方案是使用共享内存,例如分享父母的孩子列表并让孩子.add.remove他们自己?但我对此并不太了解.

编辑:另一个可能的解决方案,这是我想到的第一件事,就是简单地添加一个sleep(1)开头/* child stuff */但对我来说闻起来很有趣,这就是为什么我把它排除在外.我甚至不确定它是100%修复.

那么,你如何纠正这种竞争条件?如果有一个完善的推荐模式,请告诉我!

谢谢.



1> qrdl..:

最简单的解决方案是在处理pid之后阻止SIGCHLD信号fork(),sigprocmask()并在父代码中解除阻塞.

如果孩子死亡,在解锁信号后将调用SIGCHLD的信号处理程序.这是一个关键的部分概念 - 在您的情况下,关键部分在之前fork()和之后开始children.add().

推荐阅读
jerry613
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有