From: Colm MacCarthaigh Date: Wed, 24 Aug 2005 16:58:11 +0000 (+0000) Subject: Implement "de-listening" for graceful restarts with the prefork MPM. With this X-Git-Tag: 2.3.0~3084 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aacf3609d204659c87a0cc3687d0758f69da2af4;p=apache Implement "de-listening" for graceful restarts with the prefork MPM. With this change; 1.) httpd -k graceful sends SIGUSR1 to the parent pid, which in turn sends SIGUSR1 to all of the active children, 2.) Active children each close their copy of listener fd's. This means that the listening sockets are freed for re-use. In the ordinary case, this makes no difference. However if for example admin changes "Listen 80" to "Listen 81" in the config, this rev makes port 80 immediately available (no waiting for the graceful children to die). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@239711 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index 0afe6f0bdd..7ba2638bf4 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -331,6 +331,11 @@ static void just_die(int sig) clean_child_exit(0); } +static void stop_listening(int sig) +{ + ap_close_listeners(); +} + /* volatile just in case */ static int volatile shutdown_pending; static int volatile restart_pending; @@ -715,10 +720,10 @@ static int make_child(server_rec *s, int slot) */ apr_signal(SIGHUP, just_die); apr_signal(SIGTERM, just_die); - /* The child process doesn't do anything for AP_SIG_GRACEFUL. - * Instead, the pod is used for signalling graceful restart. + /* The child process just closes listeners on AP_SIG_GRACEFUL. + * The pod is used for signalling the graceful restart. */ - apr_signal(AP_SIG_GRACEFUL, SIG_IGN); + apr_signal(AP_SIG_GRACEFUL, stop_listening); child_main(slot); } @@ -1096,6 +1101,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* we've been told to restart */ apr_signal(SIGHUP, SIG_IGN); + apr_signal(AP_SIG_GRACEFUL, SIG_IGN); if (one_process) { /* not worth thinking about */ return 1; @@ -1123,6 +1129,14 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) for (index = 0; index < ap_daemons_limit; ++index) { if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL; + /* Ask each child to close its listeners. + * + * NOTE: we use the scoreboard, because if we send SIGUSR1 + * to every process in the group, this may include CGI's, + * piped loggers, etc. They almost certainly won't handle + * it gracefully. + */ + kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); } } }