/**
  * @param WebsocketStartEvent $event
  */
 public function start(WebsocketStartEvent $event)
 {
     $this->pcntl = new PCNTL($event->getLoop());
     foreach ($this->signals as $signal) {
         $this->pcntl->on($signal, function ($signal) use($event) {
             EventManager::instance()->dispatch(SignalEvent::create($event->getLoop(), $signal));
         });
     }
 }
Example #2
0
 public function testRegisterSignalHandler()
 {
     $pcntl = new PCNTL($this->loop);
     $pcntl->on(SIGTERM, function () {
     });
     $listeners = $pcntl->listeners(SIGTERM);
     $this->assertEquals(1, count($listeners));
     $this->assertInternalType('array', self::$pcntl_signal_args);
     $this->assertEquals(SIGTERM, self::$pcntl_signal_args[0]);
     $this->assertSame(array($pcntl, 'emit'), self::$pcntl_signal_args[1]);
 }
 public static function create($fqcn)
 {
     if (!is_subclass_of($fqcn, Application::class)) {
         throw new \InvalidArgumentException('Should be a subclass of Application');
     }
     $loop = Factory::create();
     $application = new $fqcn();
     $application->loop($loop);
     $shutdown = function () use($application) {
         $application->loop()->stop();
         $application->cleanWorkers();
     };
     $pcntl = new PCNTL($loop);
     $pcntl->on(SIGINT, $shutdown);
     $application->on('shutdown', $shutdown);
     $application->pcntl($pcntl);
     $application->on('worker.created', function (Worker $worker) use($application) {
         $application->addWorker($worker);
     });
     return $application;
 }
Example #4
0
 public function __construct($loop, $queues = null, $worker_ttl = -1)
 {
     $this->loop = $loop;
     $this->worker_ttl = $worker_ttl;
     $pcntl = new ReactPCNTL\PCNTL($loop);
     $pcntl->on(SIGCHLD, function () {
         $pid = pcntl_wait($status);
         if (isset($this->workers[$pid])) {
             $worker = $this->workers[$pid];
             $worker->emit('exit', [pcntl_wexitstatus($status)]);
             // permanent workers should not die
             if ($worker->permanent) {
                 $worker->emit('fail', [pcntl_wexitstatus($status)]);
             } else {
                 $worker->emit('done');
             }
             unset($this->workers[$pid]);
         } else {
             for ($i = 0; $i < count($this->pool); $i++) {
                 if ($this->pool[$i]->pid == $pid) {
                     array_splice($this->pool, $i, 1);
                     $this->NewWorkerUnit();
                     break;
                 }
             }
         }
     });
     $pcntl->on(SIGUSR2, function () {
         print "Workers:\n";
         foreach ($this->pool as $worker) {
             print "[I] {$worker->pid} ttl={$worker->ttl}\n";
         }
         foreach ($this->workers as $worker) {
             print "[R] {$worker->pid} ttl={$worker->ttl}\n";
         }
     });
     $this->sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
     for ($i = 0; $i < 2; $i++) {
         stream_set_blocking($this->sockets[$i], 0);
         //stream_set_chunk_size($this->sockets[$i], 512);
         //if ($i == 0) stream_set_read_buffer($this->sockets[$i], 512);
         //if ($i == 1) stream_set_write_buffer($this->sockets[$i], 512);
     }
     $loop->addReadStream($this->sockets[0], function ($socket) {
         do {
             $buf = stream_socket_recvfrom($socket, 512);
             if (!$buf) {
                 break;
             }
             if (strlen($buf) != 512) {
                 print "BAD NEWS\n";
             }
             $info = unpack("Npid/Nstatus", substr($buf, 0, 8));
             if (isset($this->workers[$info['pid']])) {
                 $worker = $this->workers[$info['pid']];
                 $worker->emit('exit', [$info['status']]);
                 if ($worker->ttl > 0) {
                     $worker->ttl--;
                 }
                 unset($this->workers[$info['pid']]);
                 $this->pool[] = $worker;
             } else {
                 $workers = array_filter($this->pool, function ($worker) use($info) {
                     return $worker->pid == $info['pid'];
                 });
                 if (count($workers) > 0) {
                     print "WORKER ALREADY IN POOL\n";
                 } else {
                     print "NO SUCH WORKER\n";
                 }
                 //print_r($worker);
             }
         } while (0);
         //$buf);
     });
     if ($queues && ($worker_ttl > 1 || $worker_ttl < 0)) {
         // Count the maximum workers and add half.
         // Good enough rule of thumb for now.
         $workernum = $queues->map(function ($queue) {
             return $queue->workers->max;
         })->reduce(function ($res, $item) {
             if ($res < $item) {
                 $res = $item;
             }
             return $res;
         }, 0);
         $workernum *= 1.5;
         $workernum = round($workernum);
         for ($i = 0; $i < $workernum; $i++) {
             $this->NewWorkerUnit();
         }
     }
 }
Example #5
0
 protected function registerSigHandlers()
 {
     if (!function_exists('pcntl_signal')) {
         $this->log(array('message' => 'Signals handling is unsupported', 'data' => array('type' => 'signal')), self::LOG_TYPE_WARNING);
         return;
     }
     $pcntl = new PCNTL($this->loop);
     $pcntl->on(SIGCHLD, function ($signo = null) {
     });
     foreach ([SIGTERM, SIGHUP, SIGINT, SIGQUIT, SIGUSR1] as $signal) {
         $pcntl->on($signal, function ($signo = null) {
             $this->shutdown();
         });
     }
     $pcntl->on(SIGUSR2, [$this, 'pauseProcessing']);
     $pcntl->on(SIGCONT, [$this, 'unPauseProcessing']);
     $pcntl->on(SIGPIPE, [$this, 'reestablishRedisConnection']);
 }
Example #6
0
 public function testRemoveAllListenersOfAllSignals()
 {
     $pcntl = new PCNTL($this->loop);
     $pcntl->on(SIGTERM, function () {
     });
     $pcntl->on(SIGHUP, function () {
     });
     $pcntl->removeAllListeners();
     $this->assertEmpty($pcntl->listeners(SIGTERM));
     $this->assertEquals(SIG_DFL, self::$pcntl_signal_args[SIGTERM]);
     $this->assertEmpty($pcntl->listeners(SIGHUP));
     $this->assertEquals(SIG_DFL, self::$pcntl_signal_args[SIGHUP]);
 }