summaryrefslogtreecommitdiffstats
path: root/vendor/gipfl/process/src/ProcessKiller.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gipfl/process/src/ProcessKiller.php')
-rw-r--r--vendor/gipfl/process/src/ProcessKiller.php81
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();
+ }
+}