Avoiding a fork()/SIGCHLD race condition

后端 未结 4 1136
情话喂你
情话喂你 2020-12-17 16:12

Please consider the following fork()/SIGCHLD pseudo-code.

  // main program excerpt
    for (;;) {
      if ( is_time_to_make_babie         


        
相关标签:
4条回答
  • 2020-12-17 16:23

    In addition to the existing "children" add a new data structure "early deaths". This will keep the contents of children clean.

      // 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
              if (!earlyDeaths.contains(pid)) {
                  children.add(pid);
              } else {
                  earlyDeaths.remove(pid);
              }
            }
    
          }
        }
    
      // SIGCHLD handler
      sigchld_handler(signo) {
        while ( (pid = wait(status, WNOHANG)) > 0 ) {
          print "parent caught SIGCHLD from ", pid
          if (children.contains(pid)) {
              children.remove(pid);
          } else {
              earlyDeaths.add(pid);
          }
        }
      }
    

    EDIT: this can be simplified if your process is single threaded -- earlyDeaths doesn't have to be a container, it just has to hold one pid.

    0 讨论(0)
  • 2020-12-17 16:36

    Maybe an optimistic algorithm? Try children.remove(pid), and if it fails, move on with life.

    Or check that pid is in children before trying to remove it?

    0 讨论(0)
  • 2020-12-17 16:38

    Simplest solution would be to block SIGCHLD signal before fork() with sigprocmask() and unblock it in parent code after you have processed the pid.

    If child died, signal handler for SIGCHLD will be called after you unblock the signal. It is a critical section concept - in your case critical section starts before fork() and ends after children.add().

    0 讨论(0)
  • 2020-12-17 16:43

    If you can't use critical fragment, maybe a simple counter can do this job. +1 when add, -1 when remove, no mater which one happen first, you eventually can get zero when all is done.

    0 讨论(0)
提交回复
热议问题