From 7e2c857ee885cada866ae5c9a43613f002ec11c4 Mon Sep 17 00:00:00 2001 From: Lucas Bustamante Date: Wed, 7 Feb 2024 00:44:15 -0300 Subject: [PATCH 1/3] [Process] Fix Inconsistent Exit Status in proc_get_status for PHP Versions Below 8.3 --- Process.php | 14 +++++++++++ Tests/ProcessTest.php | 55 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Process.php b/Process.php index 2b6ed9ef..a4b0a784 100644 --- a/Process.php +++ b/Process.php @@ -80,6 +80,7 @@ class Process implements \IteratorAggregate private $processPipes; private $latestSignal; + private $cachedExitCode; private static $sigchild; @@ -1345,6 +1346,19 @@ protected function updateStatus(bool $blocking) $this->processInformation = proc_get_status($this->process); $running = $this->processInformation['running']; + // In PHP < 8.3, "proc_get_status" only returns the correct exit status on the first call. + // Subsequent calls return -1 as the process is discarded. This workaround caches the first + // retrieved exit status for consistent results in later calls, mimicking PHP 8.3 behavior. + if (\PHP_VERSION_ID < 80300) { + if (!isset($this->cachedExitCode) && !$running && -1 !== $this->processInformation['exitcode']) { + $this->cachedExitCode = $this->processInformation['exitcode']; + } + + if (isset($this->cachedExitCode) && !$running && -1 === $this->processInformation['exitcode']) { + $this->processInformation['exitcode'] = $this->cachedExitCode; + } + } + $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running); if ($this->fallbackStatus && $this->isSigchildEnabled()) { diff --git a/Tests/ProcessTest.php b/Tests/ProcessTest.php index daf842e1..059d59a4 100644 --- a/Tests/ProcessTest.php +++ b/Tests/ProcessTest.php @@ -1541,6 +1541,60 @@ public function testEnvCaseInsensitiveOnWindows() } } + public function testMultipleCallsToProcGetStatus() + { + $process = $this->getProcess('echo foo'); + $process->start(static function () use ($process) { + return $process->isRunning(); + }); + while ($process->isRunning()) { + usleep(1000); + } + $this->assertSame(0, $process->getExitCode()); + } + + public function testFailingProcessWithMultipleCallsToProcGetStatus() + { + $process = $this->getProcess('exit 123'); + $process->start(static function () use ($process) { + return $process->isRunning(); + }); + while ($process->isRunning()) { + usleep(1000); + } + $this->assertSame(123, $process->getExitCode()); + } + + /** + * @group slow + */ + public function testLongRunningProcessWithMultipleCallsToProcGetStatus() + { + $process = $this->getProcess('php -r "sleep(1); echo \'done\';"'); + $process->start(static function () use ($process) { + return $process->isRunning(); + }); + while ($process->isRunning()) { + usleep(1000); + } + $this->assertSame(0, $process->getExitCode()); + } + + /** + * @group slow + */ + public function testLongRunningProcessWithMultipleCallsToProcGetStatusError() + { + $process = $this->getProcess('php -r "sleep(1); echo \'failure\'; exit(123);"'); + $process->start(static function () use ($process) { + return $process->isRunning(); + }); + while ($process->isRunning()) { + usleep(1000); + } + $this->assertSame(123, $process->getExitCode()); + } + /** * @group transient-on-windows */ @@ -1556,7 +1610,6 @@ public function testNotTerminableInputPipe() /** * @param string|array $commandline - * @param mixed $input */ private function getProcess($commandline, ?string $cwd = null, ?array $env = null, $input = null, ?int $timeout = 60): Process { From 4fdf34004f149cc20b2f51d7d119aa500caad975 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois <2144837+alexandre-daubois@users.noreply.github.com> Date: Mon, 12 Feb 2024 15:55:24 +0100 Subject: [PATCH 2/3] [Process] Fix failing tests causing segfaults --- Tests/ProcessTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/ProcessTest.php b/Tests/ProcessTest.php index 059d59a4..a2e370de 100644 --- a/Tests/ProcessTest.php +++ b/Tests/ProcessTest.php @@ -1570,7 +1570,7 @@ public function testFailingProcessWithMultipleCallsToProcGetStatus() */ public function testLongRunningProcessWithMultipleCallsToProcGetStatus() { - $process = $this->getProcess('php -r "sleep(1); echo \'done\';"'); + $process = $this->getProcess('sleep 1 && echo "done" && php -r "exit(0);"'); $process->start(static function () use ($process) { return $process->isRunning(); }); @@ -1585,7 +1585,7 @@ public function testLongRunningProcessWithMultipleCallsToProcGetStatus() */ public function testLongRunningProcessWithMultipleCallsToProcGetStatusError() { - $process = $this->getProcess('php -r "sleep(1); echo \'failure\'; exit(123);"'); + $process = $this->getProcess('sleep 1 && echo "failure" && php -r "exit(123);"'); $process->start(static function () use ($process) { return $process->isRunning(); }); From 710e27879e9be3395de2b98da3f52a946039f297 Mon Sep 17 00:00:00 2001 From: Kay Wei Date: Tue, 20 Feb 2024 16:24:14 +0800 Subject: [PATCH 3/3] Fix the `command -v` exception when the command option with a dash prefix --- ExecutableFinder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ExecutableFinder.php b/ExecutableFinder.php index cc789603..8c7bf58d 100644 --- a/ExecutableFinder.php +++ b/ExecutableFinder.php @@ -72,7 +72,7 @@ public function find(string $name, ?string $default = null, array $extraDirs = [ } } - $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; + $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v --'; if (\function_exists('exec') && ($executablePath = strtok(@exec($command.' '.escapeshellarg($name)), \PHP_EOL)) && @is_executable($executablePath)) { return $executablePath; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy