Ejemplo n.º 1
0
 public function __construct($name, $pid, Error $error = null)
 {
     $this->name = $name;
     $this->pid = $pid;
     $this->error = $error;
     if ($error) {
         if (__CLASS__ === $error->getClass()) {
             parent::__construct(sprintf('%s via "%s" fork (%d)', $error->getMessage(), $name, $pid));
         } else {
             parent::__construct(sprintf('%s (%d) thrown in "%s" fork (%d): "%s" (%s:%d)', $error->getClass(), $error->getCode(), $name, $pid, $error->getMessage(), $error->getFile(), $error->getLine()));
         }
     } else {
         parent::__construct(sprintf('An unknown error occurred in "%s" fork (%d)', $name, $pid));
     }
 }
Ejemplo n.º 2
0
 /**
  * Forks something into another process and returns a deferred object.
  */
 public function fork($callable)
 {
     if (!is_callable($callable)) {
         throw new UnexpectedTypeException($callable, 'callable');
     }
     // allow the system to cleanup before forking
     $this->dispatcher->dispatch(Events::PRE_FORK);
     if (-1 === ($pid = pcntl_fork())) {
         throw new ProcessControlException('Unable to fork a new process');
     }
     if (0 === $pid) {
         // reset the list of child processes
         $this->forks = array();
         // setup the fifo (blocks until parent connects)
         $fifo = new Fifo(null, $this->signal);
         $message = new ExitMessage();
         // phone home on shutdown
         register_shutdown_function(function () use(&$fifo, &$message) {
             $status = null;
             try {
                 $fifo->send($message, false);
             } catch (\Exception $e) {
                 // probably an error serializing the result
                 $message->setResult(null);
                 $message->setError(Error::fromException($e));
                 $fifo->send($message, false);
                 exit(2);
             }
         });
         // dispatch an event so the system knows it's in a new process
         $this->dispatcher->dispatch(Events::POST_FORK);
         if (!$this->debug) {
             ob_start();
         }
         try {
             $result = call_user_func($callable, $fifo);
             $message->setResult($result);
             $status = is_integer($result) ? $result : 0;
         } catch (\Exception $e) {
             $message->setError(Error::fromException($e));
             $status = 1;
         }
         if (!$this->debug) {
             $message->setOutput(ob_get_clean());
         }
         exit($status);
     }
     // connect to the fifo
     $fifo = new Fifo($pid);
     return $this->forks[$pid] = new Fork($pid, $fifo, $this->debug);
 }