|  | <?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 | 
|  | */ | 
|  | protected $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; | 
|  | } | 
|  | } |