Beispiel #1
0
 /**
  * @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;
     }
 }
Beispiel #2
0
 /**
  * @param string                 $socketAddress
  * @param WorkerBootstrapProfile $bootstrapProfile
  * @param int|null               $timeout
  *
  * @throws Exception\ConnectException
  *
  * @return ChannelInterface
  */
 private static function connect($socketAddress, WorkerBootstrapProfile $bootstrapProfile, $timeout = null)
 {
     $socket = SocketFactory::createClientSocket($socketAddress, $timeout);
     $connection = Source::fromStream($socket, true, null, false);
     return $bootstrapProfile->getChannelFactory()->createChannel(new BufferedSource($connection), $connection);
 }
Beispiel #3
0
 /**
  * @param SharedWorkerImplementationInterface $workerImpl
  * @param string                              $socketAddress
  *
  * @throws Exception\BindOrListenException
  * @throws Exception\RuntimeException
  */
 public static function runSharedWorker(SharedWorkerImplementationInterface $workerImpl, $socketAddress)
 {
     $server = self::startListening($socketAddress);
     try {
         $loop = self::getLoop();
         $loop->addReadStream($server, function () use($loop, $server, $workerImpl) {
             $socket = stream_socket_accept($server);
             $peerName = stream_socket_get_name($socket, true);
             $connection = Source::fromStream($socket, true, null, false);
             $channel = self::getChannelFactory()->createChannel(new BufferedSource($connection), $connection);
             Selectable::registerRead($loop, $channel, function () use($loop, $channel, $peerName, $workerImpl) {
                 try {
                     $message = $channel->receiveMessage();
                 } catch (IOException\UnderflowException $e) {
                     Selectable::unregisterRead($loop, $channel);
                     $workerImpl->onDisconnect($channel);
                     return;
                 }
                 if (AdminEncoding::isStopMessage($message, self::$adminCookie, $privileged)) {
                     if ($privileged) {
                         $lock = Lock::acquire();
                         self::stopListening();
                         $workerImpl->onStop();
                         $lock->release();
                     }
                 } elseif (AdminEncoding::isQueryMessage($message, self::$adminCookie, $privileged)) {
                     $result = $workerImpl->onQuery($privileged);
                     if (!$result instanceof WorkerStatus) {
                         $result = new WorkerStatus($result);
                     }
                     AdminEncoding::sendStatusMessage($channel, $result);
                 } else {
                     $workerImpl->onMessage($message, $channel, $peerName);
                 }
             });
             $workerImpl->onConnect($channel, $peerName);
         });
         $workerImpl->setLoop($loop);
         $workerImpl->initialize();
         $loop->run();
         $workerImpl->terminate();
     } finally {
         self::stopListening();
     }
 }