From b4403eee066df2c1b3dad0caef446195b2cacd2b Mon Sep 17 00:00:00 2001 From: Niklas Keller Date: Tue, 14 Dec 2021 00:53:30 +0100 Subject: [PATCH] Don't kill on __destruct if streams are still used (#59) --- src/Internal/ProcHolder.php | 21 +++++++++++++++++++++ src/Process.php | 19 +++++++++++-------- test/ProcessTest.php | 13 +++++++++++++ 3 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 src/Internal/ProcHolder.php diff --git a/src/Internal/ProcHolder.php b/src/Internal/ProcHolder.php new file mode 100644 index 0000000..de143b2 --- /dev/null +++ b/src/Internal/ProcHolder.php @@ -0,0 +1,21 @@ +runner = $runner; + $this->handle = $handle; + } + + public function __destruct() + { + $this->runner->destroy($this->handle); + } +} diff --git a/src/Process.php b/src/Process.php index 21e641d..8be9e87 100644 --- a/src/Process.php +++ b/src/Process.php @@ -8,6 +8,7 @@ use Amp\Process\Internal\Posix\PosixRunner as PosixProcessRunner; use Amp\Process\Internal\ProcessHandle; use Amp\Process\Internal\ProcessRunner; use Amp\Process\Internal\ProcessStatus; +use Amp\Process\Internal\ProcHolder; use Amp\Process\Internal\Windows\WindowsRunner as WindowsProcessRunner; use JetBrains\PhpStorm\ArrayShape; use Revolt\EventLoop; @@ -16,6 +17,8 @@ final class Process { private static \WeakMap $driverRunner; + private static \WeakMap $procHolder; + /** * Starts a new process. * @@ -63,6 +66,14 @@ final class Process $options ); + $procHolder = new ProcHolder($runner, $handle); + + /** @psalm-suppress RedundantPropertyInitializationCheck */ + self::$procHolder ??= new \WeakMap(); + self::$procHolder[$handle->stdin] = $procHolder; + self::$procHolder[$handle->stdout] = $procHolder; + self::$procHolder[$handle->stderr] = $procHolder; + return new self($runner, $handle, $command, $workingDirectory, $envVars, $options); } @@ -95,14 +106,6 @@ final class Process $this->options = $options; } - /** - * Stops the process if it is still running. - */ - public function __destruct() - { - $this->runner->destroy($this->handle); - } - public function __clone() { throw new \Error("Cloning " . self::class . " is not allowed."); diff --git a/test/ProcessTest.php b/test/ProcessTest.php index 31964d1..1e9a8a1 100644 --- a/test/ProcessTest.php +++ b/test/ProcessTest.php @@ -235,6 +235,19 @@ class ProcessTest extends AsyncTestCase self::assertSame(0, $process->join()); } + public function testReadOutputAfterExitWithLongOutputDestructedProcess(): void + { + $process = Process::start(["php", __DIR__ . "/bin/worker.php"]); + + $count = 128 * 1024 + 1; + $process->getStdin()->write("exit " . $count); + $stdout = $process->getStdout(); + + unset($process); + + self::assertSame(\str_repeat(".", $count), buffer($stdout)); + } + public function testKillPHPImmediately(): void { $socket = \stream_socket_server("tcp://127.0.0.1:10000");