/** * @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)); }); } }
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; }
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(); } } }
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']); }
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]); }