blob: e2370cb093de5d41e6084af03fdea1dac50218a1 [file] [log] [blame]
Bryan Duxburyc0e2ef52011-01-26 18:25:17 +00001<?php
2
3include_once $GLOBALS['THRIFT_ROOT'].'/server/TServer.php';
4
5/**
6 * A forking implementation of a Thrift server.
7 *
8 * @package thrift.server
9 */
10class TForkingServer extends TServer {
11 /**
12 * Flag for the main serving loop
13 *
14 * @var bool
15 */
16 private $stop_ = false;
17
18 /**
19 * List of children.
20 *
21 * @var array
22 */
Jake Farrellebf0bec2011-04-20 15:23:26 +000023 protected $children_ = array();
Bryan Duxburyc0e2ef52011-01-26 18:25:17 +000024
25 /**
26 * Listens for new client using the supplied
27 * transport. We fork when a new connection
28 * arrives.
29 *
30 * @return void
31 */
32 public function serve() {
33 $this->transport_->listen();
34
35 while (!$this->stop_) {
36 try {
37 $transport = $this->transport_->accept();
38
39 if ($transport != null) {
40 $pid = pcntl_fork();
41
42 if ($pid > 0) {
43 $this->handleParent($transport, $pid);
44 }
45 else if ($pid === 0) {
46 $this->handleChild($transport);
47 }
48 else {
49 throw new TException('Failed to fork');
50 }
51 }
52 }
53 catch (TTransportException $e) { }
54
55 $this->collectChildren();
56 }
57 }
58
59 /**
60 * Code run by the parent
61 *
62 * @param TTransport $transport
63 * @param int $pid
64 * @return void
65 */
66 private function handleParent(TTransport $transport, $pid) {
67 $this->children_[$pid] = $transport;
68 }
69
70 /**
71 * Code run by the child.
72 *
73 * @param TTransport $transport
74 * @return void
75 */
76 private function handleChild(TTransport $transport) {
77 try {
78 $inputTransport = $this->inputTransportFactory_->getTransport($transport);
79 $outputTransport = $this->outputTransportFactory_->getTransport($transport);
80 $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
81 $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
82 while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
83 @$transport->close();
84 }
85 catch (TTransportException $e) { }
86
87 exit(0);
88 }
89
90 /**
91 * Collects any children we may have
92 *
93 * @return void
94 */
95 private function collectChildren() {
96 foreach ($this->children_ as $pid => $transport) {
97 if (pcntl_waitpid($pid, $status, WNOHANG) > 0) {
98 unset($this->children_[$pid]);
99 if ($transport) @$transport->close();
100 }
101 }
102 }
103
104 /**
105 * Stops the server running. Kills the transport
106 * and then stops the main serving loop
107 *
108 * @return void
109 */
110 public function stop() {
111 $this->transport_->close();
112 $this->stop_ = true;
113 }
114}