list($type, $payload) = (yield from $transmitter->receive()); if ($type === SocketTransmitter::TYPE_EXIT) { yield from $transmitter->send($payload, $type); $socket->close(); $exitCode = 0; break; } try { if (isset($payload['func'])) { if (\substr($payload['func'], 0, 1) === '@') { $result = \substr($payload['func'], 1)(...$payload['args'] ?? []); } else { $result = $payload['func'](...$payload['args'] ?? []); } } elseif (isset($payload['class']) && isset($payload['method'])) { $result = $payload['class']::{$payload['method']}(...$payload['args'] ?? []); } else { throw new \RuntimeException('No callable target passed to threaded worker'); } } catch (\Throwable $e) { yield from $transmitter->sendError($e); continue; } yield from $transmitter->send($result, SocketTransmitter::TYPE_DATA); } } finally { Loop::stop(); } }); }, new NativeLoop()); exit($exitCode);
public function run(Container $container, callable $action) { $logger = LoopConfig::getLogger(); if ($this->running === 0) { foreach ($this->loggers as $handler) { $logger->addHandler($handler); } } $this->running++; try { $buffer = ''; if ($this->ipc) { ob_start(function (string $data, int $phase) use(&$buffer) { $buffer .= $data; return ''; }, 1, \PHP_OUTPUT_HANDLER_FLUSHABLE); } Loop::execute(function () use($container, $action, $logger, &$buffer) { Loop::setErrorHandler(function (\Throwable $e) use($logger) { $logger->critical('', ['exception' => $e]); }); $watcher = Loop::repeat(500, function () use(&$buffer, $logger) { if ($buffer !== '') { try { $this->ipc->sendOutput($buffer); } finally { $buffer = ''; } } }); Loop::unreference($watcher); if ($this->contextName === 'development') { $locator = $container->get(ResourceLocator::class); $watcher = Loop::repeat(5000, function () use($locator) { $locator->syncFiles(); }); Loop::unreference($watcher); } if ($this->ipc) { $this->ipc->run(); } $signal = function () { if ($this->ipc) { $this->ipc->stop(); } Loop::stop(); }; // Shutdown on SIGTERM. try { Loop::onSignal(15, $signal); } catch (UnsupportedFeatureException $e) { // signal handling is not available... } $action(); }); } finally { if ($this->ipc) { \ob_end_clean(); } $this->running--; if ($this->running === 0) { foreach ($this->loggers as $handler) { $logger->removeHandler($handler); } } } }
protected function listenForExit() : \Generator { try { yield from $this->transmitter->receive(); } finally { $this->stop(); $this->socket->close(); Loop::stop(); } }