| <?php | 
 |  | 
 | include_once $GLOBALS['THRIFT_ROOT'].'/server/TServer.php'; | 
 |  | 
 | /** | 
 |  * A forking implementation of a Thrift server. | 
 |  * | 
 |  * @package thrift.server | 
 |  */ | 
 | class TForkingServer extends TServer { | 
 |   /** | 
 |    * Flag for the main serving loop | 
 |    * | 
 |    * @var bool | 
 |    */ | 
 |   private $stop_ = false; | 
 |  | 
 |   /** | 
 |    * List of children. | 
 |    * | 
 |    * @var array | 
 |    */ | 
 |   private $children_ = array(); | 
 |  | 
 |   /** | 
 |    * Listens for new client using the supplied | 
 |    * transport. We fork when a new connection | 
 |    * arrives. | 
 |    * | 
 |    * @return void | 
 |    */ | 
 |   public function serve() { | 
 |     $this->transport_->listen(); | 
 |  | 
 |     while (!$this->stop_) { | 
 |       try { | 
 |         $transport = $this->transport_->accept(); | 
 |  | 
 |         if ($transport != null) { | 
 |           $pid = pcntl_fork(); | 
 |  | 
 |           if ($pid > 0) { | 
 |             $this->handleParent($transport, $pid); | 
 |           } | 
 |           else if ($pid === 0) { | 
 |             $this->handleChild($transport); | 
 |           } | 
 |           else { | 
 |             throw new TException('Failed to fork'); | 
 |           } | 
 |         } | 
 |       } | 
 |       catch (TTransportException $e) { } | 
 |  | 
 |       $this->collectChildren(); | 
 |     } | 
 |   } | 
 |  | 
 |   /** | 
 |    * Code run by the parent | 
 |    * | 
 |    * @param TTransport $transport | 
 |    * @param int $pid | 
 |    * @return void | 
 |    */ | 
 |   private function handleParent(TTransport $transport, $pid) { | 
 |     $this->children_[$pid] = $transport; | 
 |   } | 
 |  | 
 |   /** | 
 |    * Code run by the child. | 
 |    * | 
 |    * @param TTransport $transport | 
 |    * @return void | 
 |    */ | 
 |   private function handleChild(TTransport $transport) { | 
 |     try { | 
 |       $inputTransport = $this->inputTransportFactory_->getTransport($transport); | 
 |       $outputTransport = $this->outputTransportFactory_->getTransport($transport); | 
 |       $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport); | 
 |       $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport); | 
 |       while ($this->processor_->process($inputProtocol, $outputProtocol)) { } | 
 |       @$transport->close(); | 
 |     } | 
 |     catch (TTransportException $e) { } | 
 |      | 
 |     exit(0); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Collects any children we may have | 
 |    * | 
 |    * @return void | 
 |    */ | 
 |   private function collectChildren() { | 
 |     foreach ($this->children_ as $pid => $transport) { | 
 |       if (pcntl_waitpid($pid, $status, WNOHANG) > 0) { | 
 |         unset($this->children_[$pid]); | 
 |         if ($transport) @$transport->close(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   /** | 
 |    * Stops the server running. Kills the transport | 
 |    * and then stops the main serving loop | 
 |    * | 
 |    * @return void | 
 |    */ | 
 |   public function stop() { | 
 |     $this->transport_->close(); | 
 |     $this->stop_ = true; | 
 |   } | 
 | } |