-*- coding: utf-8 -*-
Changes with Apache 2.1.8
+ *) prefork, worker and event MPMs: Prevent children from holding open
+ listening ports upon graceful restart or stop. PR 28167.
+ [Colm MacCarthaigh, Brian Pinkerton <bp thinkpink.com>]
+
*) SECURITY: CAN-2005-2700 (cve.mitre.org)
mod_ssl: Fix a security issue where "SSLVerifyClient" was not
enforced in per-location context if "SSLVerifyClient optional"
*/
AP_DECLARE(int) ap_setup_listeners(server_rec *s);
+/**
+ * Loop through the global ap_listen_rec list and close each of the sockets.
+ */
+AP_DECLARE_NONSTD(void) ap_close_listeners(void);
+
/* Although these functions are exported from libmain, they are not really
* public functions. These functions are actually called while parsing the
* config file, when one of the LISTEN_COMMANDS directives is read. These
apr_signal(SIGCHLD, SIG_IGN);
apr_signal(SIGHUP, daemon_signal_handler);
+ /* Close our copy of the listening sockets */
+ ap_close_listeners();
+
/* cgid should use its own suexec doer */
ap_hook_get_suexec_identity(cgid_suexec_id_doer, NULL, NULL,
APR_HOOK_REALLY_FIRST);
static apr_status_t close_listeners_on_exec(void *v)
{
- ap_listen_rec *lr;
-
- for (lr = ap_listeners; lr; lr = lr->next) {
- apr_socket_close(lr->sd);
- lr->active = 0;
- }
-
+ ap_close_listeners();
return APR_SUCCESS;
}
-
static const char *alloc_listener(process_rec *process, char *addr,
apr_port_t port, const char* proto)
{
return num_listeners;
}
+AP_DECLARE_NONSTD(void) ap_close_listeners(void) {
+ ap_listen_rec *lr;
+
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ apr_socket_close(lr->sd);
+ lr->active = 0;
+ }
+}
+
AP_DECLARE(void) ap_listen_pre_config(void)
{
old_listeners = ap_listeners;
} /* listener main loop */
+ ap_close_listeners();
ap_queue_term(worker_queue);
dying = 1;
ap_scoreboard_image->parent[process_slot].quiescing = 1;
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;
*/
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 graceful restart.
*/
- apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
+ apr_signal(AP_SIG_GRACEFUL, stop_listening);
child_main(slot);
}
/* 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;
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);
}
}
}
}
}
+ ap_close_listeners();
ap_queue_term(worker_queue);
dying = 1;
ap_scoreboard_image->parent[process_slot].quiescing = 1;