Skip to content

Commit 37b1292

Browse files
committed
Fix bug #77023: FPM cannot shutdown processes
1 parent 2f0918c commit 37b1292

File tree

3 files changed

+83
-5
lines changed

3 files changed

+83
-5
lines changed

sapi/fpm/fpm/fpm_process_ctl.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ int fpm_pctl_kill(pid_t pid, int how) /* {{{ */
138138
case FPM_PCTL_QUIT :
139139
s = SIGQUIT;
140140
break;
141+
case FPM_PCTL_KILL:
142+
s = SIGKILL;
143+
break;
141144
default :
142145
break;
143146
}
@@ -310,6 +313,17 @@ static void fpm_pctl_check_request_timeout(struct timeval *now) /* {{{ */
310313
}
311314
/* }}} */
312315

316+
static void fpm_pctl_kill_idle_child(struct fpm_child_s *child) /* {{{ */
317+
{
318+
if (child->idle_kill) {
319+
fpm_pctl_kill(child->pid, FPM_PCTL_KILL);
320+
} else {
321+
child->idle_kill = 1;
322+
fpm_pctl_kill(child->pid, FPM_PCTL_QUIT);
323+
}
324+
}
325+
/* }}} */
326+
313327
static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ */
314328
{
315329
struct fpm_worker_pool_s *wp;
@@ -372,8 +386,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
372386
fpm_request_last_activity(last_idle_child, &last);
373387
fpm_clock_get(&now);
374388
if (last.tv_sec < now.tv_sec - wp->config->pm_process_idle_timeout) {
375-
last_idle_child->idle_kill = 1;
376-
fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_QUIT);
389+
fpm_pctl_kill_idle_child(last_idle_child);
377390
}
378391

379392
continue;
@@ -385,8 +398,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
385398
zlog(ZLOG_DEBUG, "[pool %s] currently %d active children, %d spare children, %d running children. Spawning rate %d", wp->config->name, active, idle, wp->running_children, wp->idle_spawn_rate);
386399

387400
if (idle > wp->config->pm_max_spare_servers && last_idle_child) {
388-
last_idle_child->idle_kill = 1;
389-
fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_QUIT);
401+
fpm_pctl_kill_idle_child(last_idle_child);
390402
wp->idle_spawn_rate = 1;
391403
continue;
392404
}

sapi/fpm/fpm/fpm_process_ctl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ enum {
4444
FPM_PCTL_TERM,
4545
FPM_PCTL_STOP,
4646
FPM_PCTL_CONT,
47-
FPM_PCTL_QUIT
47+
FPM_PCTL_QUIT,
48+
FPM_PCTL_KILL
4849
};
4950

5051
#endif
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
--TEST--
2+
FPM: Blocked SIGQUIT prevents idle process to be killed
3+
--EXTENSIONS--
4+
pcntl
5+
--SKIPIF--
6+
<?php
7+
include "skipif.inc";
8+
if (!function_exists('pcntl_sigprocmask')) die('skip Requires pcntl_sigprocmask()');
9+
if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request');
10+
?>
11+
--FILE--
12+
<?php
13+
14+
require_once "tester.inc";
15+
16+
$cfg = <<<EOT
17+
[global]
18+
error_log = {{FILE:LOG}}
19+
pid = {{FILE:PID}}
20+
[unconfined]
21+
listen = {{ADDR}}
22+
pm.status_path = /status
23+
pm = dynamic
24+
pm.max_children = 2
25+
pm.start_servers = 1
26+
pm.min_spare_servers = 1
27+
pm.max_spare_servers = 1
28+
EOT;
29+
30+
$code = <<<EOT
31+
<?php
32+
pcntl_sigprocmask(SIG_BLOCK, [SIGQUIT, SIGTERM]);
33+
usleep(300000);
34+
EOT;
35+
36+
37+
$tester = new FPM\Tester($cfg, $code);
38+
$tester->start();
39+
$tester->expectLogStartNotices();
40+
$tester->multiRequest(2);
41+
$tester->status([
42+
'total processes' => 2,
43+
]);
44+
// wait for process to be killed
45+
sleep(7);
46+
$tester->expectLogWarning('child \\d+ exited on signal 9 \\(SIGKILL\\) after \\d+.\\d+ seconds from start', 'unconfined');
47+
$tester->expectLogNotice('child \\d+ started', 'unconfined');
48+
$tester->expectLogWarning('child \\d+ exited on signal 9 \\(SIGKILL\\) after \\d+.\\d+ seconds from start', 'unconfined');
49+
$tester->expectLogNotice('child \\d+ started', 'unconfined');
50+
$tester->status([
51+
'total processes' => 1,
52+
]);
53+
$tester->terminate();
54+
$tester->expectLogTerminatingNotices();
55+
$tester->close();
56+
57+
?>
58+
Done
59+
--EXPECT--
60+
Done
61+
--CLEAN--
62+
<?php
63+
require_once "tester.inc";
64+
FPM\Tester::clean();
65+
?>

0 commit comments

Comments
 (0)