diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index e26819b5bca17..0e98862ba51a5 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.1 +--- + + * Add support for `Fiber` + 6.4 --- diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index c95afabc0a5f4..e69d2ef2d5894 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -429,12 +429,31 @@ public function wait(?callable $callback = null): int do { $this->checkTimeout(); $running = $this->isRunning() && ('\\' === \DIRECTORY_SEPARATOR || $this->processPipes->areOpen()); - $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); + if ($fiber = \Fiber::getCurrent()) { + $this->readPipes(false, '\\' !== \DIRECTORY_SEPARATOR || !$running); + $startedAt = microtime(true); + $fiber->suspend(); + $sleepFor = (int) (1000 - (microtime(true) - $startedAt) * 1000000); + if (0 < $sleepFor) { + usleep($sleepFor); + } + } else { + $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); + } } while ($running); while ($this->isRunning()) { $this->checkTimeout(); - usleep(1000); + if ($fiber = \Fiber::getCurrent()) { + $startedAt = microtime(true); + $fiber->suspend(); + $sleepFor = (int) (1000 - (microtime(true) - $startedAt) * 1000000); + if (0 < $sleepFor) { + usleep($sleepFor); + } + } else { + usleep(1000); + } } if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) { diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index d027cc507e783..fbf47a2f7474c 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -587,6 +587,27 @@ public function testMustRun() $this->assertEquals('foo'.\PHP_EOL, $process->getOutput()); } + public function testMustRunWithFiber() + { + $process = new Process(['sleep', 1]); + $fiber = new \Fiber(function () use ($process) { + $process->mustRun(); + }); + $fiber->start(); + + $fiberHasBeenSuspended = false; + while (!$fiber->isTerminated()) { + $fiberHasBeenSuspended = true; + $this->assertTrue($fiber->isSuspended()); + $fiber->resume(); + + usleep(900); + } + + $this->assertTrue($process->isTerminated()); + $this->assertTrue($fiberHasBeenSuspended); + } + public function testSuccessfulMustRunHasCorrectExitCode() { $process = $this->getProcess('echo foo')->mustRun();