TForkingServer.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. <?php
  2. namespace Thrift\Server;
  3. use Thrift\Transport\TTransport;
  4. use Thrift\Exception\TException;
  5. use Thrift\Exception\TTransportException;
  6. /**
  7. * A forking implementation of a Thrift server.
  8. *
  9. * @package thrift.server
  10. */
  11. class TForkingServer extends TServer
  12. {
  13. /**
  14. * Flag for the main serving loop
  15. *
  16. * @var bool
  17. */
  18. private $stop_ = false;
  19. /**
  20. * List of children.
  21. *
  22. * @var array
  23. */
  24. protected $children_ = array();
  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. {
  34. $this->transport_->listen();
  35. while (!$this->stop_) {
  36. try {
  37. $transport = $this->transport_->accept();
  38. if ($transport != null) {
  39. $pid = pcntl_fork();
  40. if ($pid > 0) {
  41. $this->handleParent($transport, $pid);
  42. } elseif ($pid === 0) {
  43. $this->handleChild($transport);
  44. } else {
  45. throw new TException('Failed to fork');
  46. }
  47. }
  48. } catch (TTransportException $e) { }
  49. $this->collectChildren();
  50. }
  51. }
  52. /**
  53. * Code run by the parent
  54. *
  55. * @param TTransport $transport
  56. * @param int $pid
  57. * @return void
  58. */
  59. private function handleParent(TTransport $transport, $pid)
  60. {
  61. $this->children_[$pid] = $transport;
  62. }
  63. /**
  64. * Code run by the child.
  65. *
  66. * @param TTransport $transport
  67. * @return void
  68. */
  69. private function handleChild(TTransport $transport)
  70. {
  71. try {
  72. $inputTransport = $this->inputTransportFactory_->getTransport($transport);
  73. $outputTransport = $this->outputTransportFactory_->getTransport($transport);
  74. $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
  75. $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
  76. while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
  77. @$transport->close();
  78. } catch (TTransportException $e) { }
  79. exit(0);
  80. }
  81. /**
  82. * Collects any children we may have
  83. *
  84. * @return void
  85. */
  86. private function collectChildren()
  87. {
  88. foreach ($this->children_ as $pid => $transport) {
  89. if (pcntl_waitpid($pid, $status, WNOHANG) > 0) {
  90. unset($this->children_[$pid]);
  91. if ($transport) @$transport->close();
  92. }
  93. }
  94. }
  95. /**
  96. * Stops the server running. Kills the transport
  97. * and then stops the main serving loop
  98. *
  99. * @return void
  100. */
  101. public function stop()
  102. {
  103. $this->transport_->close();
  104. $this->stop_ = true;
  105. }
  106. }