title: Spawn and detach PHP process without sharing any db-resources so that the child can exit?
body: <p>I want an "eternal" process that goes through a MySQL table and spawns child processes. Pseudo code:</p>
  
  <pre><code>while(true)
      $rows = SELECT * FROM workers
      foreach($rows as $row){
           DELETE $row-&gt;id
           spawn_child($row-&gt;id)
      }
      sleep(5)
  }
  function spawn_child($id){
       $pid = pcntl_fork()
       if($pid &lt;0){
           //err
       }elseif($pid == 0){
           //child
           exec("worker_program $id");
           exit();
       }elseif($pid &gt; 0){
           //parent
       }
   }
  </code></pre>
  
  <p>The problem is that when the child process comes back from the worker_program and exits, it closes the apparently shared mysql-handle, so the parent process gets a "<strong>Msql server went away</strong>"-error. </p>
  
  <p>How do I solve this? Is it a design fault?</p>
  
  <p><em>How do I spawn and detach a process in PHP, without sharing any db resources etc, so that the child is free to exit?</em></p>
  
  <p>(I have tried: setsid and forking again, calling workers with '<code>worker_program &amp;</code>' instead of forking in php, but that doesn't seem to work at all (weird?). I'm using PDO. Also the guys over at php.net say this behaviour is not a bug. This is on osx and php5.3 (and debian).)</p>
  
  <p>Refs.:</p>
  
  <p>php.net/bug: <a href="http://bugs.php.net/bug.php?id=37998" rel="nofollow noreferrer">"Parent process lost MySQLi connection after child process gone"</a> </p>
  
  <p><strong>Update/workaround</strong></p>
  
  <p>So I've finally found a way to deal with this. What works is to use <code>popen</code> to spawn the worker processes. That way it seems a completely "fresh" process is created, without any shares. I then let the child do the forking and detaching itself. So in the master process, instead of <code>pcntl_fork</code> or <code>exec</code>:</p>
  
  <pre><code>$p = popen("worker_program $arg","r");
  sleep(1); //give it time to detach (won't work otherwise. Any other ideas?)
  pclose($p);
  </code></pre>
  
  <p>And then in the worker program:</p>
  
  <pre><code>#!/usr/bin/env php
  &lt;?php
  
  //fully detach from parent, as proposed by the 'gurus'
  //(Why can't this be done with only one fork?)
  if(pcntl_fork()) {
      exit();
  }
  posix_setsid();
  if(pcntl_fork()) {
      exit();
  }
  ...
  </code></pre>