Пример #1
0
 /** @internal */
 public function go(Process $process)
 {
     $this->deferred = $deferred = new Deferred();
     $this->process = $process;
     $buffered = null;
     $process->stdout->on('data', function ($data) use(&$buffered) {
         if ($data !== '') {
             $buffered .= $data;
         }
     });
     $process->on('exit', function ($code) use($deferred) {
         if ($code !== 0) {
             $deferred->reject($code);
         } else {
             $deferred->resolve();
         }
     });
     $that = $this;
     $this->promise = $deferred->promise()->then(function () use(&$buffered, $that) {
         if ($buffered === null) {
             $buffered = true;
         } else {
             $buffered = $that->parseValue(trim($buffered));
         }
         return $buffered;
     });
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $arguments = $this->getCommandArguments($input);
     $builder = $this->getEnvironmentHelper()->getProcessBuilder($arguments);
     $command = $builder->getProcess()->getCommandLine();
     $loop = Factory::create();
     $process = new Process($command, $this->getEnvironmentHelper()->getCwd());
     $port = (int) $input->getOption('port');
     $server = $this->initializeServer($loop, $port);
     $started = false;
     $this->addEnvironmentInfo($port, $command);
     $loop->addPeriodicTimer(self::LOOP_TIMER_PERIOD, function (Timer $timer) use($output, $process, $server, &$started) {
         $clients = $server->getConnections();
         if (true === $started && false === $process->isRunning()) {
             exit($process->getExitCode());
         }
         if ($clients->count()) {
             if (!$process->isRunning()) {
                 $process->start($timer->getLoop());
                 $started = true;
                 $this->broadcastToClients($clients);
             }
             $callable = function ($output) use($clients) {
                 $this->buffer .= $output;
                 $this->broadcastToClients($clients);
             };
             $process->stdin->on('data', $callable);
             $process->stdout->on('data', $callable);
             $process->stderr->on('data', $callable);
         }
     });
     $server->bind();
     $loop->run();
 }
 /**
  * @param Process $process
  * @param LoopInterface $loop
  * @param array $options
  * @param float $interval
  * @return \React\Promise\PromiseInterface
  */
 public static function parent(Process $process, LoopInterface $loop, array $options = [], $interval = self::INTERVAL)
 {
     $process->start($loop, $interval);
     return \WyriHaximus\React\tickingPromise($loop, $interval, [$process, 'isRunning'])->then(function () use($process, $options) {
         $messenger = new Messenger($process->stdin, $process->stdout, $process->stderr, ['read_err' => 'stderr', 'read' => 'stdout', 'write' => 'stdin', 'callForward' => function ($name, $arguments) use($process) {
             return call_user_func_array([$process, $name], $arguments);
         }] + $options);
         Util::forwardEvents($process, $messenger, ['exit']);
         return \React\Promise\resolve($messenger);
     });
 }
Пример #4
0
 public function testTerminatingProcessReturnsError()
 {
     $process = new Process('echo nevermind && cat');
     $process->start($this->loop);
     $zen = new BaseZen();
     $zen->go($process);
     $this->loop->addTimer(0.1, function () use($process) {
         $process->terminate(SIGKILL);
     });
     $this->loop->run();
     $zen->promise()->then(null, $this->expectCallableOnce());
 }
Пример #5
0
 /**
  * launch the given interactive $command shell
  *
  * Its STDOUT will be used to parse responses, the STDIN will be used
  * to pass commands.
  *
  * If the command prints output to STDERR, make sure to redirect it to
  * STDOUT by appending " 2>&1".
  *
  * @param string|Process $process accepts either a command string to execute or a Process instance
  * @return DeferredShell
  */
 public function createDeferredShell($process)
 {
     if (!$process instanceof Process) {
         $process = new Process($process);
     }
     $process->start($this->loop);
     $stream = new CompositeStream($process->stdout, $process->stdin);
     // forcefully terminate process when stream closes
     $stream->on('close', function () use($process) {
         if ($process->isRunning()) {
             $process->terminate(SIGKILL);
         }
     });
     return new DeferredShell($stream);
 }
Пример #6
0
 public function close()
 {
     if ($this->out !== null) {
         $this->out->removeAllListeners();
     }
     if ($this->in !== null) {
         $this->in->removeAllListeners();
     }
     if ($this->err !== null) {
         $this->err->removeAllListeners();
     }
     $this->process->removeAllListeners();
     if ($this->process->isRunning()) {
         $this->process->terminate();
     }
 }
Пример #7
0
 /**
  * @param Process $process
  * @return null
  * @throws CommandsExecutionException
  */
 public static function tryTerminateProcess(Process $process)
 {
     try {
         $terminationResult = $process->terminate();
         if (!$terminationResult) {
             throw new CommandsExecutionException("Process termination for PID " . $process->getPid() . " wasn't success");
         }
     } catch (\Exception $e) {
         try {
             self::sendSig($process->getPid(), SIGKILL);
         } catch (\Exception $e) {
             throw new CommandsExecutionException("SIGKILL for PID " . $process->getPid() . " wasn't success");
         }
     }
     return null;
 }
 public function __construct($host = '127.0.0.1', $docroot = null, $router = null, $php = PHP_BINARY)
 {
     $port = mt_rand(49152, 65535);
     $command = implode(' ', array_filter([escapeshellarg($php), '-S', escapeshellarg("{$host}:{$port}"), $docroot !== null ? '-t ' . escapeshellarg($docroot) : null, $router !== null ? escapeshellarg($router) : null], 'is_string'));
     parent::__construct($command, null, null, ['bypass_shell' => true]);
     $this->host = $host;
     $this->port = $port;
 }
/**
 * Promise that resolves once child process exits
 *
 * @param LoopInterface $loop    ReactPHP event loop.
 * @param Process       $process Child Process to run.
 *
 * @return \React\Promise\PromiseInterface
 */
function childProcessPromise(LoopInterface $loop, Process $process)
{
    $deferred = new Deferred();
    $buffers = ['stderr' => '', 'stdout' => ''];
    $process->on('exit', function ($exitCode) use($deferred, &$buffers) {
        $deferred->resolve(new ProcessOutcome($exitCode, $buffers['stderr'], $buffers['stdout']));
    });
    \WyriHaximus\React\futurePromise($loop, $process)->then(function (Process $process) use($loop, &$buffers) {
        $process->start($loop);
        $process->stderr->on('data', function ($output) use(&$buffers) {
            $buffers['stderr'] .= $output;
        });
        $process->stdout->on('data', function ($output) use(&$buffers) {
            $buffers['stdout'] .= $output;
        });
    });
    return $deferred->promise();
}
 /**
  * @return PromiseInterface
  */
 public function execute($program = '')
 {
     if ($program === '') {
         return new RejectedPromise();
     }
     $deferred = new Deferred();
     $process = new Process('exec hash ' . $program);
     $process->on('exit', function ($exitCode) use($deferred) {
         if ($exitCode == 0) {
             $deferred->resolve();
             return;
         }
         $deferred->reject();
     });
     \WyriHaximus\React\futurePromise($this->loop, $process)->then(function (Process $process) {
         $process->start($this->loop);
     });
     return $deferred->promise();
 }
 /**
  * @return PromiseInterface
  */
 public function execute()
 {
     $deferred = new Deferred();
     $buffer = '';
     $process = new Process('exec nproc');
     $process->on('exit', function ($exitCode) use($deferred, &$buffer) {
         if ($exitCode == 0) {
             $deferred->resolve($buffer);
             return;
         }
         $deferred->reject();
     });
     \WyriHaximus\React\futurePromise($this->loop, $process)->then(function (Process $process) use(&$buffer) {
         $process->start($this->loop);
         $process->stdout->on('data', function ($output) use(&$buffer) {
             $buffer += $output;
         });
     });
     return $deferred->promise();
 }
Пример #12
0
 public function runTestProcess($arguments, $expectedExitCode = 0, $timeout = 5)
 {
     $command = __DIR__ . '/../../../../bin/phpunit-parallel ' . $arguments;
     $loop = Factory::create();
     $p = new Process($command);
     $p->start($loop);
     $stdout = '';
     $stderr = '';
     $timer = $loop->addTimer($timeout, function () use($arguments, $p, $stdout, $stderr) {
         $p->terminate(SIGKILL);
         $this->fail("running phpunit-parallel with '{$arguments}' did not complete in time\nstdout: {$stdout}\nstderr: {$stderr}\n");
     });
     $p->stdout->on('data', function ($data) use(&$stdout) {
         $stdout .= $data;
     });
     $p->stderr->on('data', function ($data) use(&$stderr) {
         $stderr .= $data;
     });
     $p->on('exit', function () use($timer) {
         $timer->cancel();
     });
     $loop->run();
     if ($p->getExitCode() !== $expectedExitCode) {
         $this->fail("Process exited with code {$p->getExitCode()}, expected {$expectedExitCode}\nstdout: {$stdout}\nstderr: {$stderr}\n");
     }
     return [$stdout, $stderr];
 }
Пример #13
0
    /**
     *
     */
    public function serverAction($argv)
    {
        $config = $this->di->getConfig();
        $help = <<<HELPMSG
* PHP Ratchet websocket server on port {$config->app->wsPort}
* ZMQ server on port {$config->app->zmqPort}
* Node.js/Gulp Webpack build environment server on port {$config->dev->webpackPort}
HELPMSG;
        $params = $this->parseArgs($argv, ['title' => "Start the dev (development) server processes", 'help' => $help, 'args' => ['required' => [], 'optional' => []], 'opts' => []]);
        $devDir = $this->config->dev->path->devDir;
        $cmdWebirdEsc = escapeshellcmd("{$devDir}/webird.php");
        $devDirEsc = escapeshellarg($devDir);
        $websocketProc = new Process("{$cmdWebirdEsc} websocket");
        $webpackProc = new Process("cd {$devDirEsc} && npm run dev");
        $loop = EventLoopFactory::create();
        $loop->addTimer(0.001, function ($timer) use($websocketProc, $webpackProc) {
            $websocketProc->start($timer->getLoop());
            $this->addProcOutputListener($websocketProc);
            $webpackProc->start($timer->getLoop());
            $this->addProcOutputListener($webpackProc);
        });
        $loop->run();
    }
Пример #14
0
    /**
     *
     */
    public function serverAction($argv)
    {
        $config = $this->config;
        $help = <<<HELPMSG
* PHP Ratchet websocket server on port {$config->app->wsPort}
* ZMQ server on port {$config->app->zmqPort}
HELPMSG;
        $params = $this->parseArgs($argv, ['title' => 'Start the dist (distribution/production) server processes.', 'help' => $help, 'args' => ['required' => [], 'optional' => []], 'opts' => ['w|wsport:' => "websockets listen on port (default is {$config->app->wsPort}).", 'z|zmqport:' => "zmq listen on port (default is {$config->app->zmqPort})."]]);
        $appDir = $this->config->path->appDir;
        $cmdWebirdEsc = escapeshellcmd("{$appDir}/webird.php");
        $websocketProc = new Process("{$cmdWebirdEsc} websocket");
        $loop = EventLoopFactory::create();
        $loop->addTimer(0.001, function ($timer) use($websocketProc) {
            $websocketProc->start($timer->getLoop());
            $websocketProc->stdout->on('data', function ($output) {
                echo $output;
            });
            $websocketProc->stderr->on('data', function ($output) {
                echo $output;
            });
        });
        $loop->run();
    }
Пример #15
0
 /**
  * {@inheritdoc}
  * @param LoopInterface $loop
  * @param float $interval
  */
 public function start(LoopInterface $loop, $interval = 0.1)
 {
     if ($this->isRunning()) {
         return;
     }
     $this->startedAt = microtime(true);
     $this->once('exit', function ($exitCode, $termSignal) use($loop) {
         $this->startedAt = null;
         //Auto restart
         if ($termSignal !== 15 && $this->autoRestart === true) {
             $this->start($loop);
         }
     });
     parent::start($loop, $interval);
 }
Пример #16
0
 /**
  * @return null
  * @throws \CommandsExecutor\Inventory\Exceptions\CommandsExecutionException
  */
 protected function stopReplyStack()
 {
     LinuxCommands::sendSigTermOrKill($this->commandsManager->getPidByPpid($this->replyStackProcess->getPid())->getPid());
     LinuxCommands::tryTerminateProcess($this->replyStackProcess);
     return null;
 }
 /**
  * @param InputInterface $input
  * @param OutputInterface $output
  *
  * @return void
  */
 protected function executeMultiThreadStreamManager(InputInterface $input, OutputInterface $output)
 {
     /** @var Generator $streams */
     $streams = $this->getContainer()->get('sim.event_store.replay')->streams();
     $loop = Factory::create();
     $threads = 0;
     $iteration = 0;
     $loop->addPeriodicTimer(0.001, function ($timer) use($loop, $streams, &$threads, &$iteration, $input, $output) {
         if ($threads >= $input->getOption('threads')) {
             return;
         }
         if (!$streams->valid()) {
             $loop->stop();
         }
         $threads++;
         $stream = $streams->current();
         $output->writeln(sprintf('<info>Dispatching thread for event stream %s</info>', $stream));
         $process = new Process(sprintf('app/console simgroep:eventsourcing:events:replay %s --stream %s', $input->getArgument('projector'), $stream));
         $process->on('exit', function ($exitCode, $termSignal) use(&$threads, $output) {
             $threads--;
             if ($exitCode !== 0) {
                 $output->writeln(sprintf('<error>Process ended with code %s</error>', $exitCode));
             }
         });
         $process->start($timer->getLoop());
         if ($input->getOption('verbose')) {
             $process->stdout->on('data', function ($message) use($output) {
                 $output->write($message);
             });
         }
         $output->writeln(sprintf('<info>Stream %s | %s streams/sec</info>', str_pad(++$iteration, 10, ' ', STR_PAD_LEFT), str_pad($this->perSecond($iteration), 6, ' ', STR_PAD_LEFT)));
         $streams->next();
     });
     $loop->run();
 }
Пример #18
0
 private function run(array $args = array())
 {
     $command = $this->bin;
     foreach ($args as $value) {
         $command .= ' ' . escapeshellarg($value);
     }
     // var_dump($command);
     $process = new Process($command);
     $process->start($this->loop);
     return $process;
 }
 /**
  * Start process on the loop passed
  */
 public function start(LoopInterface $loop, $interval = 0.1)
 {
     $this->send(self::EVENT_BEFORE_START);
     // Initialize variables
     $this->loop = $loop;
     $this->elapsed = 1;
     // The first time this is used, one second is elapsed already
     $this->hanged = false;
     // Start process
     parent::start($this->loop, $interval);
     if (!$this->hasTimer()) {
         // For every tick of the timer, check if process is hanging,
         // and update elapsed time
         $self = $this;
         $timer =& $this->timer;
         $elapsed =& $this->elapsed;
         $hanged =& $this->hanged;
         $this->timer = $loop->addPeriodicTimer(1, function (TimerInterface $t) use($self, &$timer, &$elapsed, &$hanged) {
             $self->send($self::EVENT_ELAPSED);
             // If process is hanging, interrupt it
             if ($self->isHanging()) {
                 $hanged = true;
                 $self->send($self::EVENT_HANGING);
                 $self->terminate();
             }
             // Increment elapsed time
             $elapsed++;
         });
     }
     $this->send(self::EVENT_AFTER_START);
 }
Пример #20
0
 protected function queueProcess()
 {
     if (!$this->benchmarks->valid()) {
         return;
     }
     $b = $this->benchmarks->current();
     $this->benchmarks->next();
     $key = serialize([$b->benchmark, $b->subbenchmark, $b->count]);
     if (!isset($this->stdout[$key])) {
         $this->stdout[$key] = '';
     }
     if (!isset($this->runtimes[$key])) {
         $this->runtimes[$key] = [];
     }
     $current_process_id = $this->process_id;
     $this->process_id++;
     $this->processes[$current_process_id] = $process = new Process($b->command);
     $start = null;
     $process->on('exit', function ($code, $signal) use($b, $key, &$current_process_id, &$start) {
         $this->runtimes[$key][] = microtime(true) - $start;
         $this->output->writeln('<comment>End ' . $b->benchmark . '-' . $b->subbenchmark . ' ' . $b->count . ' #' . $b->execution . '</comment>');
         unset($this->processes[$current_process_id]);
         $this->queueProcess();
     });
     $this->loop->addTimer(0.001, function ($timer) use($process, $key, $b, &$start) {
         $this->output->writeln('<comment>Start ' . $b->benchmark . '-' . $b->subbenchmark . ' ' . $b->count . ' #' . $b->execution . '</comment>');
         $start = microtime(true);
         $process->start($timer->getLoop());
         $process->stdout->on('data', function ($data) use(&$stdout, $key) {
             $this->stdout[$key] .= $data;
         });
     });
 }
Пример #21
0
 public function testTerminateWithStopAndContinueSignalsUsingEventLoop()
 {
     if (defined('PHP_WINDOWS_VERSION_BUILD')) {
         $this->markTestSkipped('Windows does not report signals via proc_get_status()');
     }
     if (!defined('SIGSTOP') && !defined('SIGCONT')) {
         $this->markTestSkipped('SIGSTOP and/or SIGCONT is not defined');
     }
     $loop = $this->createloop();
     $process = new Process('sleep 1; exit 0');
     $called = false;
     $exitCode = 'initial';
     $termSignal = 'initial';
     $process->on('exit', function () use(&$called, &$exitCode, &$termSignal) {
         $called = true;
         $exitCode = func_get_arg(0);
         $termSignal = func_get_arg(1);
     });
     $loop->addTimer(0.001, function (Timer $timer) use($process) {
         $process->start($timer->getLoop());
         $process->terminate(SIGSTOP);
         $this->assertSoon(function () use($process) {
             $this->assertTrue($process->isStopped());
             $this->assertTrue($process->isRunning());
             $this->assertEquals(SIGSTOP, $process->getStopSignal());
         });
         $process->terminate(SIGCONT);
         $this->assertSoon(function () use($process) {
             $this->assertFalse($process->isStopped());
             $this->assertEquals(SIGSTOP, $process->getStopSignal());
         });
     });
     $loop->run();
     $this->assertTrue($called);
     $this->assertSame(0, $exitCode);
     $this->assertNull($termSignal);
     $this->assertFalse($process->isRunning());
     $this->assertSame(0, $process->getExitCode());
     $this->assertNull($process->getTermSignal());
     $this->assertFalse($process->isTerminated());
 }
Пример #22
0
 /**
  * Runs the application
  *
  * @return void
  */
 public function run()
 {
     if (!self::$defaultApplication) {
         self::$defaultApplication = $this;
     }
     $application = $this;
     if (OsDetector::isMacOS()) {
         $processName = './phpgui-i386-darwin';
         $processPath = __DIR__ . '/../lazarus/phpgui-i386-darwin.app/Contents/MacOS/';
     } elseif (OsDetector::isFreeBSD()) {
         $processName = './phpgui-x86_64-freebsd';
         $processPath = __DIR__ . '/../lazarus/';
     } elseif (OsDetector::isUnix()) {
         $processName = './phpgui-x86_64-linux';
         $processPath = __DIR__ . '/../lazarus/';
     } elseif (OsDetector::isWindows()) {
         $processName = '.\\phpgui-x86_64-win64';
         $processPath = __DIR__ . '\\..\\lazarus\\';
     } else {
         throw new RuntimeException('Operational System not identified by PHP-GUI.');
     }
     $this->process = $process = new Process($processName, $processPath);
     $this->process->on('exit', function () use($application) {
         $application->loop->stop();
     });
     $this->receiver = $receiver = new Receiver($this);
     $this->sender = $sender = new Sender($this, $receiver);
     $this->loop->addTimer(0.001, function ($timer) use($process, $application, $receiver) {
         $process->start($timer->getLoop());
         // We need to pause all default streams
         // The react/loop uses fread to read data from streams
         // On Windows, fread always is blocking
         // Stdin is paused, we use our own way to write on it
         $process->stdin->pause();
         // Stdout is paused, we use our own way to read it
         $process->stdout->pause();
         // Stderr is paused for avoiding fread
         $process->stderr->pause();
         $process->stdout->on('data', function ($data) use($receiver) {
             $receiver->onData($data);
         });
         $process->stderr->on('data', function ($data) {
             if (!empty($data)) {
                 Output::err($data);
             }
         });
         $application->running = true;
         // Bootstrap the application
         $application->fire('start');
     });
     $this->loop->addPeriodicTimer(0.001, function () use($application) {
         $application->sender->tick();
         if (@is_resource($application->process->stdout->stream)) {
             $application->receiver->tick();
         }
     });
     $this->loop->run();
 }
Пример #23
0
 public function tryTerminateProcess(Process $process)
 {
     try {
         $terminationResult = $process->terminate();
         if (!$terminationResult) {
             throw new ReactManagerException("Process termination for PID " . $process->getPid() . " wasn't success");
         }
     } catch (\Exception $e) {
         try {
             $this->logAndSendSigKill($process->getPid(), $e);
         } catch (\Exception $e) {
             $this->logger->warning("Parent process can't be sigKilled.");
         }
     }
     return null;
 }