|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2019-04-24 09:54 UTC] marc+bugsphp at cdmon dot com
Description: ------------ When you try to restart graceful php-fpm it holds untill process_control_timeout triggers and sends TERM to each child. This happens from version 7.1.20 and 7.2.8, the fix that brokes this was http://bugs.php.net/73342 the update was at 19 Jul 2018. I was debugging the logs and found that the master process sends the SIGQUIT to the childs, and then no reply from childs to master happens since process_control_timeout stops: >>> [24-Apr-2019 10:14:26.740642] DEBUG: pid 23148, fpm_pctl_kill_all(), line 157: [pool marctestqa.com] sending signal 3 SIGQUIT to child 23165 The logs stucks on fpm_event_loop for process_control_timeout time, then makes another fpm_pctl_kill_all but with SIGTERM: >>> [24-Apr-2019 10:14:26.740697] DEBUG: pid 23148, fpm_event_loop(), line 417: event module triggered 1 events >>> [24-Apr-2019 10:14:46.741631] DEBUG: pid 23148, fpm_pctl_kill_all(), line 157: [pool marctestqa.com] sending signal 15 SIGTERM to child 23165 Ok, fpm_event_loop is a timer that waits to the fpm_event_queue_fd: >>> ret = module->wait(fpm_event_queue_fd, timeout); (line 409, file fpm_events.c, php 7.3.4) I will suppose that on debian the module system is epoll, then module = fpm_event_epoll_module();, and then we have .wait = fpm_event_epoll_wait, ret = fpm_event_epoll_module->fpm_event_epoll_wait(fd,t) And I can't follow this because I don't have more Linux internals knowledge. Test script: --------------- edit php-fpm.conf and put some time into process_control_timeout: [global] process_control_timeout = 20s Then open 2 terminals, in one call: watch -n0,1 "systemctl status php-fpm.service". On the other term call: kill -USR2 PHPFPMPID*. then see how it waits the 20 seconds and force the kill (SIGTERM) onto all the childrens. If you try this into 7.0 or prior to 7.2.8 or 7.1.20 it works. *: PHPFPMPID: The current process ID of the Master. Expected result: ---------------- A gradual restart of all the pools while they are freeing the sockets. Actual result: -------------- Wait till process_control_timeout, then SIGTERM all the pools. Patchesfpm_kill_USR2_7.3.4_77934 (last revision 2019-05-06 09:20 UTC by marc+bugsphp at cdmon dot com)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 08:00:01 2025 UTC |
I have modified the patch from 7.2.8 that it is this: $ git diff php-7.2.7 php-7.2.8 -- sapi/fpm/fpm/fpm_children.c diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c index b48fa54f53..4ee316ba1b 100644 --- a/sapi/fpm/fpm/fpm_children.c +++ b/sapi/fpm/fpm/fpm_children.c @@ -146,6 +146,7 @@ static struct fpm_child_s *fpm_child_find(pid_t pid) /* {{{ */ static void fpm_child_init(struct fpm_worker_pool_s *wp) /* {{{ */ { fpm_globals.max_requests = wp->config->pm_max_requests; + fpm_globals.listening_socket = dup(wp->listening_socket); if (0 > fpm_stdio_init_child(wp) || 0 > fpm_log_init_child(wp) || $ git diff php-7.2.7 php-7.2.8 -- sapi/fpm/fpm/fpm_stdio.c diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c index 40720176e1..76e8b324df 100644 --- a/sapi/fpm/fpm/fpm_stdio.c +++ b/sapi/fpm/fpm/fpm_stdio.c @@ -103,12 +103,6 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ fpm_globals.error_log_fd = -1; zlog_set_fd(-1); - if (wp->listening_socket != STDIN_FILENO) { - if (0 > dup2(wp->listening_socket, STDIN_FILENO)) { - zlog(ZLOG_SYSERROR, "failed to init child stdio: dup2()"); - return -1; - } - } return 0; } /* }}} */ and it worked as spected, restarting the childrens at moment of doing kill -USR2 PID. I need to add to this, that I'm using a 0 request server, is a test server to just test this bug. Thanks.I have been looking to the fpm_signals.c and noticed that we still try to close standard input which might cause this issue. It's done in sig_soft_quit function. So maybe this could fix it: diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c index 1b97025ea7..caf41e8a3f 100644 --- a/sapi/fpm/fpm/fpm_signals.c +++ b/sapi/fpm/fpm/fpm_signals.c @@ -142,7 +142,7 @@ static void sig_soft_quit(int signo) /* {{{ */ int saved_errno = errno; /* closing fastcgi listening socket will force fcgi_accept() exit immediately */ - close(0); + close(fpm_globals.listening_socket); if (0 > socket(AF_UNIX, SOCK_STREAM, 0)) { zlog(ZLOG_WARNING, "failed to create a new socket"); }