Skip to content

Commit 4d32bf4

Browse files
committed
php-fpm: graceful restart without blocking/losing requests
## Issue: When php-fpm gets "graceful" reloaded it will stop accepting requests while finishing reqests it already received. If those requests to finish are of a long running kind like big uploads over a slow connection, this will block new requests to be handled for an unacceptable long time. ### Current behavior ``` | v FPM (OLD) running | v $ sudo kill -USR2 $(cat /run/php-fpm/php-fpm.pid) | v OLD sends SIGQUIT to children v OLD stops handling requests | v OLD keeps running until all children complete or time out | v OLD exec()s v FPM (NEW) starts & re-uses listening socket | v NEW handles incoming requests from now on ``` ## Proposed Solution: In the case of a reloading request, we immediately fork and exec a new fpm instance to seamlessly handle new requests, while the old instance keeps finishing those requests already accepted. ### New behavior ``` | v FPM (OLD) running | v $ sudo kill -USR2 $(cat /run/php-fpm/php-fpm.pid) | v OLD sends SIGQUIT to children v OLD fork()s & exec()s |\ | \ | v FPM (NEW) starts & re-uses listening socket | v NEW handles incoming requests from now on | | v | OLD keeps running until all children complete or time out v | OLD gone - | / / v NEW still going | ``` We've been running this patch since PHP 5.6 (early 2017).
1 parent a3503f0 commit 4d32bf4

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

UPGRADING

+6
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ PHP 7.4 UPGRADE NOTES
112112
3. Changes in SAPI modules
113113
========================================
114114

115+
- FPM:
116+
. Graceful restart (SIGUSR2) behavior changed to immediately fork and exec a
117+
new FPM instance while the old instance finishes the legacy of requests.
118+
IMPORTANT NOTE: Existing start-stop scripts and/or daemon units may have to
119+
be adopted to this behavior (two instances of FPM active while reloading).
120+
115121
========================================
116122
4. Deprecated Functionality
117123
========================================

sapi/fpm/fpm/fpm_process_ctl.c

+16-3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ static void fpm_pctl_exit() /* {{{ */
7878
static void fpm_pctl_exec() /* {{{ */
7979
{
8080

81+
switch (fork()) {
82+
case 0:
83+
break;
84+
case -1:
85+
zlog(ZLOG_SYSERROR, "failed to reload: fork() failed");
86+
/* no break */
87+
default:
88+
fpm_global_config.pid_file = NULL;
89+
return;
90+
}
8191
zlog(ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\""
8292
"%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
8393
"%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
@@ -106,9 +116,8 @@ static void fpm_pctl_action_last() /* {{{ */
106116
{
107117
switch (fpm_state) {
108118
case FPM_PCTL_STATE_RELOADING:
109-
fpm_pctl_exec();
110-
break;
111-
119+
zlog(ZLOG_NOTICE, "exiting after reload");
120+
exit(FPM_EXIT_OK);
112121
case FPM_PCTL_STATE_FINISHING:
113122
case FPM_PCTL_STATE_TERMINATING:
114123
fpm_pctl_exit();
@@ -195,6 +204,10 @@ static void fpm_pctl_action_next() /* {{{ */
195204
fpm_pctl_kill_all(sig);
196205
fpm_signal_sent = sig;
197206
fpm_pctl_timeout_set(timeout);
207+
208+
if (fpm_signal_sent == SIGQUIT && fpm_state == FPM_PCTL_STATE_RELOADING) {
209+
fpm_pctl_exec();
210+
}
198211
}
199212
/* }}} */
200213

sapi/fpm/fpm/fpm_sockets.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,17 @@ static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
7474

7575
if (which == FPM_CLEANUP_PARENT_EXIT_MAIN) {
7676
if (ls->type == FPM_AF_UNIX) {
77-
unlink(ls->key);
77+
struct sockaddr_un sa_un;
78+
79+
memset(&sa_un, 0, sizeof(sa_un));
80+
strlcpy(sa_un.sun_path, ls->key, sizeof(sa_un.sun_path));
81+
sa_un.sun_family = AF_UNIX;
82+
83+
if (fpm_socket_unix_test_connect(&sa_un, sizeof(sa_un)) == 0) {
84+
zlog(ZLOG_WARNING, "Keeping unix socket, another FPM instance seems to already listen on %s", ls->key);
85+
} else {
86+
unlink(ls->key);
87+
}
7888
}
7989
}
8090
free(ls->key);

0 commit comments

Comments
 (0)