From 5f1bcca531141cd9e684be5c011ef5c62e3a545f Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 28 Oct 2026 13:33:54 +0100 Subject: [PATCH] Fix flaky FPM test for bug #77023 The test sent two parallel requests to a pool with a single child and expected the dynamic process manager to spawn a second child. That only happens when the idle server maintenance heartbeat (1s) fires while the child is busy, but the scripts kept it busy for just 300ms each, so the spawn was a matter of luck and the total processes check failed on slow machines. Use a single request that blocks the child for longer than the heartbeat so the spare child is always spawned, and rely on the fact that the blocked child is the oldest idle one and is therefore quit first. One blocked child is enough to verify the SIGKILL fallback. Replace the fixed sleep with log timeouts and poll the status until the spare child is quit. --- .../bug77023-pm-dynamic-blocking-sigquit.phpt | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt b/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt index b20d55875034..56fbffc3f9c7 100644 --- a/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt +++ b/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt @@ -2,7 +2,6 @@ FPM: Blocked SIGQUIT prevents idle process to be killed --EXTENSIONS-- pcntl ---FLAKY-- --SKIPIF-- start(extensions: ['pcntl']); $tester->expectLogStartNotices(); -$tester->multiRequest(2); +$tester->request()->expectEmptyBody(); $tester->status([ 'total processes' => 2, ]); -// wait for process to be killed -sleep(7); -$tester->expectLogWarning('child \\d+ exited on signal 9 \\(SIGKILL\\) after \\d+.\\d+ seconds from start', 'unconfined'); -$tester->expectLogNotice('child \\d+ started', 'unconfined'); -$tester->expectLogWarning('child \\d+ exited on signal 9 \\(SIGKILL\\) after \\d+.\\d+ seconds from start', 'unconfined'); +$tester->expectLogWarning( + 'child \\d+ exited on signal 9 \\(SIGKILL\\) after \\d+.\\d+ seconds from start', + 'unconfined', + timeoutSeconds: 10 +); $tester->expectLogNotice('child \\d+ started', 'unconfined'); +// wait for the remaining spare process to be quit +for ($i = 0; $i < 20; $i++) { + $status = json_decode($tester->request('json', [], '/status')->getBody('application/json'), true); + if (($status['total processes'] ?? null) === 1) { + break; + } + usleep(500000); +} $tester->status([ 'total processes' => 1, ]);