/** * @param WorkerBootstrapProfile $bootstrapProfile * @param string $implementationExpression */ protected function __construct(WorkerBootstrapProfile $bootstrapProfile, $implementationExpression) { $bootstrapProfile->getOrFindPhpExecutablePathAndArguments($php, $phpArgs); $bootstrapProfile->compileScriptWithExpression($implementationExpression, null, $scriptPath, $deleteScript); try { $line = array_merge([$php], $phpArgs, [$scriptPath]); $outPath = $bootstrapProfile->getOutputPath(); $this->process = proc_open(implode(' ', array_map('escapeshellarg', $line)), [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => $outPath !== null ? ['file', $outPath, 'a'] : STDERR], $pipes); $inputSink = Sink::fromStream($pipes[0], true); $outputSource = Source::fromStream($pipes[1], true); $this->channel = $bootstrapProfile->getChannelFactory()->createChannel($outputSource, $inputSink); } catch (\Exception $e) { if (isset($pipes[1])) { fclose($pipes[1]); } if (isset($pipes[0])) { fclose($pipes[0]); } if (isset($this->process)) { proc_terminate($this->process); proc_close($this->process); } if ($deleteScript) { unlink($scriptPath); } throw $e; } }
/** * @param RawWorkerImplementationInterface|EventedWorkerImplementationInterface $workerImpl * * @throws Exception\InvalidArgumentException */ public static function runDedicatedWorker($workerImpl) { $channel = self::getChannelFactory()->createChannel(Source::fromInput(), Sink::fromOutput()); if ($workerImpl instanceof RawWorkerImplementationInterface) { $workerImpl->run($channel); } elseif ($workerImpl instanceof EventedWorkerImplementationInterface) { $loop = self::getLoop(); Selectable::registerRead($loop, $channel, function () use($loop, $channel, $workerImpl) { try { $message = $channel->receiveMessage(); } catch (IOException\UnderflowException $e) { Selectable::unregisterRead($loop, $channel); $workerImpl->onDisconnect($channel); return; } $workerImpl->onMessage($message, $channel, null); }); $workerImpl->setLoop($loop); $workerImpl->initialize(); $workerImpl->onConnect($channel, null); $loop->run(); $workerImpl->terminate(); } else { throw new Exception\InvalidArgumentException('Bad worker implementation'); } }