diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index afd8b6b272e..6921b8b3af7 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -511,10 +511,6 @@ static function (): void { $this->argument_map[$file_path] = $argument_map; } } - - if ($pool->didHaveError()) { - exit(1); - } } else { $i = 0; diff --git a/src/Psalm/Internal/Codebase/Scanner.php b/src/Psalm/Internal/Codebase/Scanner.php index c30d6c5a022..40baaa33d14 100644 --- a/src/Psalm/Internal/Codebase/Scanner.php +++ b/src/Psalm/Internal/Codebase/Scanner.php @@ -417,10 +417,6 @@ function () { ); } } - - if ($pool->didHaveError()) { - exit(1); - } } else { $i = 0; diff --git a/src/Psalm/Internal/Fork/Pool.php b/src/Psalm/Internal/Fork/Pool.php index 08a972ede7d..9d00a104993 100644 --- a/src/Psalm/Internal/Fork/Pool.php +++ b/src/Psalm/Internal/Fork/Pool.php @@ -80,8 +80,6 @@ final class Pool /** @var resource[] */ private array $read_streams = []; - private bool $did_have_error = false; - /** @var ?Closure(mixed): void */ private ?Closure $task_done_closure = null; @@ -297,6 +295,20 @@ private static function streamForChild(array $sockets) return $for_write; } + private function killAllChildren(): void + { + foreach ($this->child_pid_list as $child_pid) { + /** + * SIGTERM does not exist on windows + * + * @psalm-suppress UnusedPsalmSuppress + * @psalm-suppress UndefinedConstant + * @psalm-suppress MixedArgument + */ + posix_kill($child_pid, SIGTERM); + } + } + /** * Read the results that each child process has serialized on their write streams. * The results are returned in an array, one for each worker. The order of the results @@ -319,6 +331,7 @@ private function readResultsFromChildren(): array $content = array_fill_keys(array_keys($streams), ''); $terminationMessages = []; + $done = []; // Read the data off of all the stream. while (count($streams) > 0) { @@ -361,34 +374,25 @@ private function readResultsFromChildren(): array if ($message instanceof ForkProcessDoneMessage) { $terminationMessages[] = $message->data; } elseif ($message instanceof ForkTaskDoneMessage) { + $done[(int)$file] = true; if ($this->task_done_closure !== null) { ($this->task_done_closure)($message->data); } } elseif ($message instanceof ForkProcessErrorMessage) { - // Kill all children - foreach ($this->child_pid_list as $child_pid) { - /** - * SIGTERM does not exist on windows - * - * @psalm-suppress UnusedPsalmSuppress - * @psalm-suppress UndefinedConstant - * @psalm-suppress MixedArgument - */ - posix_kill($child_pid, SIGTERM); - } + $this->killAllChildren(); throw new Exception($message->message); } else { - error_log('Child should return ForkMessage - response type=' . gettype($message)); - $this->did_have_error = true; + $this->killAllChildren(); + throw new Exception('Child should return ForkMessage - response type=' . gettype($message)); } } } // If the stream has closed, stop trying to select on it. if (feof($file)) { - if ($content[(int)$file] !== '') { - error_log('Child did not send full message before closing the connection'); - $this->did_have_error = true; + if ($content[(int)$file] !== '' || !isset($done[(int)$file])) { + $this->killAllChildren(); + throw new Exception('Child did not send full message before closing the connection'); } fclose($file); @@ -450,8 +454,8 @@ public function wait(): array * @psalm-suppress UndefinedConstant */ if ($term_sig !== SIGALRM) { - $this->did_have_error = true; - error_log("Child terminated with return code $return_code and signal $term_sig"); + $this->killAllChildren(); + throw new Exception("Child terminated with return code $return_code and signal $term_sig"); } } } @@ -459,12 +463,4 @@ public function wait(): array return $content; } - - /** - * Returns true if this had an error, e.g. due to memory limits or due to a child process crashing. - */ - public function didHaveError(): bool - { - return $this->did_have_error; - } } diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index 6d1dada4c3a..39927917b06 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -7,6 +7,8 @@ use function array_filter; use function array_merge; use function array_splice; +use function assert; +use function count; use function extension_loaded; use function file_get_contents; use function file_put_contents; @@ -125,7 +127,7 @@ private static function toBytes(string $value): int /** * No type hint to allow xdebug-handler v1 and v2 usage * - * @param string[] $command + * @param non-empty-list $command * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint */ protected function restart($command): void @@ -167,6 +169,7 @@ protected function restart($command): void 0, $additional_options, ); + assert(count($command) > 1); parent::restart($command); }