protected function childSignalHandler($signo, $pid = null, $status = null) { //If no pid is provided, that means we're getting the signal from the system. Let's figure out //which child process ended if (!$pid) { $pid = pcntl_waitpid(-1, $status, WNOHANG); } //Make sure we get all of the exited children while ($pid > 0) { if ($pid && isset($this->currentJobs[$pid])) { $exitCode = pcntl_wexitstatus($status); if ($exitCode != 0) { $this->logger->info("{$pid} exited with status " . $exitCode); } unset($this->currentJobs[$pid]); } else { if ($pid) { //Oh no, our job has finished before this parent process could even note that it had been launched! //Let's make note of it and handle it when the parent process is ready for it $this->logger->info("..... Adding {$pid} to the signal queue ....."); $this->signalQueue[$pid] = $status; } } $pid = pcntl_waitpid(-1, $status, WNOHANG); } return true; }
/** * @param ClientSession $session * @param InvocationMessage $msg */ public function processInvocation(ClientSession $session, InvocationMessage $msg) { foreach ($this->registrations as $key => $registration) { if (!isset($registration["registration_id"])) { $this->logger->info("Registration_id not set for " . $registration['procedure_name'] . "\n"); } else { if ($registration["registration_id"] === $msg->getRegistrationId()) { if ($registration['callback'] === null) { // this is where calls end up if the client has called unregister but // have not yet received confirmation from the router about the // unregistration $session->sendMessage(ErrorMessage::createErrorMessageFromMessage($msg, "thruway.error.unregistering")); return; } $results = $registration["callback"]($msg->getArguments(), $msg->getArgumentsKw(), $msg->getDetails()); if ($results instanceof Promise) { // the result is a promise - hook up stuff as a callback $results->then(function ($promiseResults) use($msg, $session) { $promiseResults = is_array($promiseResults) ? $promiseResults : [$promiseResults]; $promiseResults = !$this::is_list($promiseResults) ? [$promiseResults] : $promiseResults; $options = new \stdClass(); $yieldMsg = new YieldMessage($msg->getRequestId(), $options, $promiseResults); $session->sendMessage($yieldMsg); }, function ($errorUri = null, $errorArgs = null, $errorArgsKw = null) use($msg, $session, $registration) { $errorMsg = ErrorMessage::createErrorMessageFromMessage($msg); if ($errorUri !== null) { $errorMsg->setErrorURI($registration['procedure_name'] . '.error'); } else { $errorMsg->setErrorURI("thruway.invocation.error"); } if (is_array($errorArgs)) { $errorMsg->setArguments($errorArgs); } if (is_array($errorArgsKw)) { $errorMsg->setArgumentsKw($errorArgsKw); } $session->sendMessage($errorMsg); }); } else { $results = !$this::is_list($results) ? [$results] : $results; $options = new \stdClass(); $yieldMsg = new YieldMessage($msg->getRequestId(), $options, $results); $session->sendMessage($yieldMsg); } break; } } } }
/** * Launches a command as a separate process. * * The '--process-timeout' parameter can be used to set the process timeout * in seconds. Default timeout is 300 seconds. * If '--ignore-errors' parameter is specified any errors are ignored; * otherwise, an exception is raises if an error happened. * If '--disable-cache-sync' parameter is specified a synchronization of caches between current * process and its child processes are disabled. * * @param string $command * @param array $params * @param LoggerInterface|null $logger * * @return integer The exit status code * * @throws \RuntimeException if command failed and '--ignore-errors' parameter is not specified */ public function runCommand($command, $params = [], LoggerInterface $logger = null) { $params = $this->prepareParameters($command, $params); $ignoreErrors = false; if (array_key_exists('--ignore-errors', $params)) { $ignoreErrors = true; unset($params['--ignore-errors']); } $pb = new ProcessBuilder(); $pb->add($this->getPhp())->add($this->consoleCmdPath); if (array_key_exists('--process-timeout', $params)) { $pb->setTimeout($params['--process-timeout']); unset($params['--process-timeout']); } $disableCacheSync = false; if (array_key_exists('--disable-cache-sync', $params)) { $disableCacheSync = $params['--disable-cache-sync']; unset($params['--disable-cache-sync']); } foreach ($params as $name => $val) { $this->processParameter($pb, $name, $val); } $process = $pb->inheritEnvironmentVariables(true)->getProcess(); if (!$logger) { $logger = new NullLogger(); } $exitCode = $process->run(function ($type, $data) use($logger) { if ($type === Process::ERR) { $logger->error($data); } else { $logger->info($data); } }); // synchronize all data caches if ($this->dataCacheManager && !$disableCacheSync) { $this->dataCacheManager->sync(); } $this->processResult($exitCode, $ignoreErrors, $logger); return $exitCode; }