title: PHP forking and multiple child signals
body: <p>I'm trying to write a script which creates a number of forked child processes using the <a href="http://www.php.net/manual/en/ref.pcntl.php" rel="noreferrer"><code>pcntl_*</code> functions</a>.</p>
  
  <p>Basically, there is a single script which runs in a loop for about a minute, periodically polling a database to see if there is a task to be run. If there is one, it should fork and run the task in a separate process so that the parent isn't held up by a long-running task.</p>
  
  <p>Since there possibly could be a large number of tasks ready to be run, I want to limit the number of child processes that are created. Therefore, I am keeping track of the number of processes by incrementing a variable each time one is created (and then pausing if there's too many), and then decrementing it in a signal handler. Kind of like this:</p>
  
  <pre><code>define(ticks = 1);
  
  $openProcesses = 0; // how many we have open
  $max = 3;           // the most we want open at a time
  
  pcntl_signal(SIGCHLD, "childFinished");
  
  while (!time_is_up()) {
      if (there_is_something_to_do()) {
          $pid = pcntl_fork();
          if (!$pid) {      // I am the child
              foo();        //   run the long-running task
              exit(0);      //   and exit
          } else {          // I am the parent
              ++$openProcesses;
              if ($openProcesses &gt;= $max) {
                  pcntl_wait($status);    // wait for any child to exit 
              }                           // before continuing
          }
      } else {
          sleep(3);
      }
  }
  
  function childFinished($signo) {
      global $openProcesses;
      --$openProcesses;
  }
  </code></pre>
  
  <p>This works pretty much ok most of the time, except for when two or more processes finish simultaneously - the signal handler function is only called once, which throws out my counter. The reason for this is explained by "Anonymous" in the <a href="http://www.php.net/manual/en/function.pcntl-signal.php" rel="noreferrer">notes of the PHP manual</a>:</p>
  
  <blockquote>
    <p>Multiple children return less than the number of children exiting at a given moment SIGCHLD signals is normal behavior for Unix (POSIX) systems.  SIGCHLD might be read as "one or more children changed status -- go examine your children and harvest their status values". </p>
  </blockquote>
  
  <p>My question is this: <strong>How do I examine the children and harvest their status?</strong> Is there any reliable way to check how many child processes are open at any given time?</p>
  
  <p><sub><em>Using PHP 5.2.9</em></sub></p>