diff options
Diffstat (limited to 'vendor/gipfl/process/src/ProcessKiller.php')
-rw-r--r-- | vendor/gipfl/process/src/ProcessKiller.php | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/vendor/gipfl/process/src/ProcessKiller.php b/vendor/gipfl/process/src/ProcessKiller.php new file mode 100644 index 0000000..cf904ce --- /dev/null +++ b/vendor/gipfl/process/src/ProcessKiller.php @@ -0,0 +1,81 @@ +<?php + +namespace gipfl\Process; + +use React\ChildProcess\Process as ChildProcess; +use React\EventLoop\LoopInterface; +use React\Promise\Deferred; +use function React\Promise\resolve; + +class ProcessKiller +{ + /** + * @param ChildProcess $process + * @param LoopInterface $loop + * @param int $timeout + * @return \React\Promise\ExtendedPromiseInterface + */ + public static function terminateProcess(ChildProcess $process, LoopInterface $loop, $timeout = 0) + { + $processes = new ProcessList(); + $processes->attach($process); + return static::terminateProcesses($processes, $loop, $timeout); + } + + /** + * @param ProcessList $processes + * @param LoopInterface $loop + * @param int $timeout + * @return \React\Promise\ExtendedPromiseInterface + */ + public static function terminateProcesses(ProcessList $processes, LoopInterface $loop, $timeout = 5) + { + if ($processes->count() === 0) { + return resolve(); + } + $deferred = new Deferred(); + $killTimer = $loop->addTimer($timeout, function () use ($deferred, $processes, $loop) { + /** @var ChildProcess $process */ + foreach ($processes as $process) { + $pid = $process->getPid(); + // Logger::error("Process $pid is still running, sending SIGKILL"); + $process->terminate(SIGKILL); + } + + // Let's add a bit of a delay after KILLing + $loop->addTimer(0.1, function () use ($deferred) { + $deferred->resolve(); + }); + }); + + $timer = $loop->addPeriodicTimer($timeout / 20, function () use ( + $deferred, + $processes, + $loop, + &$timer, + $killTimer + ) { + $stopped = []; + /** @var ChildProcess $process */ + foreach ($processes as $process) { + if (! $process->isRunning()) { + $stopped[] = $process; + } + } + foreach ($stopped as $process) { + $processes->detach($process); + } + if ($processes->count() === 0) { + $loop->cancelTimer($timer); + $loop->cancelTimer($killTimer); + $deferred->resolve(); + } + }); + /** @var ChildProcess $process */ + foreach ($processes as $process) { + $process->terminate(SIGTERM); + } + + return $deferred->promise(); + } +} |