diff --git a/src/Utils.php b/src/Utils.php index 82c2689..d8e6948 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -24,10 +24,20 @@ public static function cpuCount(): int return 1; } - return \strtolower(\PHP_OS) === 'darwin' - ? (int) shell_exec('sysctl -n machdep.cpu.core_count') - : (int) shell_exec('nproc') - ; + $command = \strtolower(\PHP_OS) === 'darwin' + ? 'sysctl -n machdep.cpu.core_count' + : 'nproc'; + + $result = shell_exec($command); + + // shell_exec returns null (no output) or false (command failed) + if (!\is_string($result)) { + return 1; + } + + $count = (int) \trim($result); + + return $count > 0 ? $count : 1; } public static function isWindows(): bool diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 1eef9cc..110366b 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -25,6 +25,15 @@ public function testCpuCountReturnsPositiveInteger(): void $this->assertGreaterThanOrEqual(1, $cpuCount); } + public function testCpuCountNeverReturnsZero(): void + { + // Regression test for #150: Utils::cpuCount() must NEVER return 0, + // even when shell_exec('nproc') returns null (command not available) + // or produces empty/unexpected output. Returning 0 would cause + // downstream issues: zero workers spawned in ServerWorker. + $this->assertNotSame(0, Utils::cpuCount()); + } + /** * @requires OS Windows */