diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:44:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:44:51 +0000 |
commit | a1ec78bf0dc93d0e05e5f066f1949dc3baecea06 (patch) | |
tree | ee596ce1bc9840661386f96f9b8d1f919a106317 /vendor/gipfl/process | |
parent | Initial commit. (diff) | |
download | icingaweb2-module-incubator-upstream/0.20.0.tar.xz icingaweb2-module-incubator-upstream/0.20.0.zip |
Adding upstream version 0.20.0.upstream/0.20.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gipfl/process')
-rw-r--r-- | vendor/gipfl/process/composer.json | 25 | ||||
-rw-r--r-- | vendor/gipfl/process/src/FinishedProcessState.php | 66 | ||||
-rw-r--r-- | vendor/gipfl/process/src/ProcessInfo.php | 89 | ||||
-rw-r--r-- | vendor/gipfl/process/src/ProcessKiller.php | 81 | ||||
-rw-r--r-- | vendor/gipfl/process/src/ProcessList.php | 44 |
5 files changed, 305 insertions, 0 deletions
diff --git a/vendor/gipfl/process/composer.json b/vendor/gipfl/process/composer.json new file mode 100644 index 0000000..21e9971 --- /dev/null +++ b/vendor/gipfl/process/composer.json @@ -0,0 +1,25 @@ +{ + "name": "gipfl/process", + "description": "Process-related utility classes", + "type": "library", + "license": "MIT", + "autoload": { + "psr-4": { + "gipfl\\Process\\": "src/" + } + }, + "authors": [ + { + "name": "Thomas Gelf", + "email": "thomas@gelf.net" + } + ], + "require": { + "php": ">=5.6.0", + "ext-json": "*", + "react/child-process": ">=0.6", + "react/promise": "^2", + "gipfl/json": ">=0.1", + "gipfl/linux-health": ">=0.2" + } +} diff --git a/vendor/gipfl/process/src/FinishedProcessState.php b/vendor/gipfl/process/src/FinishedProcessState.php new file mode 100644 index 0000000..fd70292 --- /dev/null +++ b/vendor/gipfl/process/src/FinishedProcessState.php @@ -0,0 +1,66 @@ +<?php + +namespace gipfl\Process; + +class FinishedProcessState +{ + /** @var int|null */ + protected $exitCode; + + /** @var int|null */ + protected $termSignal; + + public function __construct($exitCode, $termSignal) + { + $this->exitCode = $exitCode; + $this->termSignal = $termSignal; + } + + public function succeeded() + { + return $this->exitCode === 0; + } + + /** + * @return int|null + */ + public function getExitCode() + { + return $this->exitCode; + } + + public function getTermSignal() + { + return $this->termSignal; + } + + public function getCombinedExitCode() + { + if ($this->exitCode === null) { + if ($this->termSignal === null) { + return 255; + } else { + return 255 + $this->termSignal; + } + } else { + return $this->exitCode; + } + } + + public function getReason() + { + if ($this->exitCode === null) { + if ($this->termSignal === null) { + return 'Process died'; + } else { + return 'Process got terminated with SIGNAL ' . $this->termSignal; + } + } else { + if ($this->exitCode === 0) { + return 'Process finished successfully'; + } else { + return 'Process exited with exit code ' . $this->exitCode; + } + } + } +} diff --git a/vendor/gipfl/process/src/ProcessInfo.php b/vendor/gipfl/process/src/ProcessInfo.php new file mode 100644 index 0000000..db740d1 --- /dev/null +++ b/vendor/gipfl/process/src/ProcessInfo.php @@ -0,0 +1,89 @@ +<?php + +namespace gipfl\Process; + +use gipfl\Json\JsonSerialization; +use gipfl\LinuxHealth\Memory; +use React\ChildProcess\Process; + +class ProcessInfo implements JsonSerialization +{ + /** @var ?int */ + protected $pid; + + /** @var string */ + protected $command; + + /** @var bool */ + protected $running; + + /** @var ?object */ + protected $memory; + + public static function forProcess(Process $process) + { + $self = new static(); + $self->pid = $process->getPid(); + $self->command = $process->getCommand(); + $self->running = $process->isRunning(); + if ($memory = Memory::getUsageForPid($self->pid)) { + $self->memory = $memory; + } + + return $self; + } + + public static function fromSerialization($any) + { + $self = new static(); + $self->pid = $any->pid; + $self->command = $any->command; + $self->running = $any->running; + $self->memory = $any->memory; + + return $self; + } + + /** + * @return int|null + */ + public function getPid() + { + return $this->pid; + } + + /** + * @return string + */ + public function getCommand() + { + return $this->command; + } + + /** + * @return bool + */ + public function isRunning() + { + return $this->running; + } + + /** + * @return object|null + */ + public function getMemory() + { + return $this->memory; + } + + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + return (object) [ + 'pid' => $this->pid, + 'command' => $this->command, + 'running' => $this->running, + 'memory' => $this->memory, + ]; + } +} 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(); + } +} diff --git a/vendor/gipfl/process/src/ProcessList.php b/vendor/gipfl/process/src/ProcessList.php new file mode 100644 index 0000000..a3f7c30 --- /dev/null +++ b/vendor/gipfl/process/src/ProcessList.php @@ -0,0 +1,44 @@ +<?php + +namespace gipfl\Process; + +/** + * @method ChildProcess current + */ +use Evenement\EventEmitterInterface; +use Evenement\EventEmitterTrait; +use InvalidArgumentException; +use React\ChildProcess\Process as ChildProcess; +use SplObjectStorage; + +class ProcessList extends SplObjectStorage implements EventEmitterInterface +{ + const ON_ATTACHED = 'attached'; + const ON_DETACHED = 'detached'; + + use EventEmitterTrait; + + #[\ReturnTypeWillChange] + public function attach($object, $info = null) + { + if (! $object instanceof ChildProcess || $info !== null) { + throw new InvalidArgumentException(sprintf( + 'Can attach only %s instances', + ChildProcess::class + )); + } + $object->on('exit', function () use ($object) { + $this->detach($object); + }); + + parent::attach($object, $info); + $this->emit(self::ON_ATTACHED, [$object]); + } + + #[\ReturnTypeWillChange] + public function detach($object) + { + parent::detach($object); + $this->emit(self::ON_DETACHED, [$object]); + } +} |