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]; }
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(); } }
/** * 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); }
/** * @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 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()); }
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; }