From: Chris Darroch Date: Fri, 26 May 2006 18:27:23 +0000 (+0000) Subject: On graceless shutdown or restart, send AP_SIG_GRACEFUL to all worker X-Git-Tag: 2.3.0~2378 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ab486bc0883a8ff27622957fd3042b6d0b467896;p=thirdparty%2Fapache%2Fhttpd.git On graceless shutdown or restart, send AP_SIG_GRACEFUL to all worker threads so that any that are polling on Keep-Alive connections will wake up and exit promptly. Otherwise, on Linux, they wait until poll()'s timeout interval completes, which is often too long for the parent process; the parent issues SIGKILL before the child's main thread manages to re-join all the worker threads. PR 38737. On Solaris, by contrast, the close_worker_sockets() function successfully alerts all worker threads that they should exit quickly. On Linux, this side-effect of one thread closing another's socket doesn't occur; see: http://bugme.osdl.org/show_bug.cgi?id=546 Also, expand on the placeholder in CHANGES regarding previous cleanups to scoreboard.c and scoreboard.h in r404848 and r404849. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@409715 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 942c058b365..8086806bce4 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.3.0 [Remove entries to the current 2.0 and 2.2 section below, when backported] + *) Worker MPM: On graceless shutdown or restart, send signals to + each worker thread to wake them up if they're polling on a + Keep-Alive connection. PR 38737. [Chris Darroch] + *) Worker and event MPMs: Remove improper scoreboard updates which were performed in the event of a fork() failure. [Chris Darroch] @@ -11,7 +15,13 @@ Changes with Apache 2.3.0 *) Add support for fcgi:// proxies to mod_rewrite. [Markus Schiegl ] - *) Tidy up scoreboard [Chris Darroch ] + *) Remove incorrect comments from scoreboard.h regarding conditional + loading of worker_score structure with mod_status, and remove unused + definitions relating to old life_status field. + [Chris Darroch ] + + *) Remove allocation of memory for unused array of lb_score pointers + in ap_init_scoreboard(). [Chris Darroch ] *) core, mod_http: add optional 'scheme://' prefix to ServerName directive. For 'https', mod_http returns "https" for the ap_hook_http_scheme and diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index a4ea5c7adf8..7f504fc5536 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -213,6 +213,19 @@ static apr_proc_mutex_t *accept_mutex; */ #define LISTENER_SIGNAL SIGHUP +/* The WORKER_SIGNAL signal will be sent from the main thread to the + * worker threads during an ungraceful restart or shutdown. + * This ensures that on systems (i.e., Linux) where closing the worker + * socket doesn't awake the worker thread when it is polling on the socket + * (especially in apr_wait_for_io_or_timeout() when handling + * Keep-Alive connections), close_worker_sockets() and join_workers() + * still function in timely manner and allow ungraceful shutdowns to + * proceed to completion. Otherwise join_workers() doesn't return + * before the main process decides the child process is non-responsive + * and sends a SIGKILL. + */ +#define WORKER_SIGNAL AP_SIG_GRACEFUL + /* An array of socket descriptors in use by each thread used to * perform a non-graceful (forced) shutdown of the server. */ static apr_socket_t **worker_sockets; @@ -822,6 +835,11 @@ static void * APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void * dummy) ap_scoreboard_image->servers[process_slot][thread_slot].generation = ap_my_generation; ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL); +#ifdef HAVE_PTHREAD_KILL + unblock_signal(WORKER_SIGNAL); + apr_signal(WORKER_SIGNAL, dummy_signal_handler); +#endif + while (!workers_may_exit) { if (!is_idle) { rv = ap_queue_info_set_idle(worker_queue_info, last_ptrans); @@ -1077,6 +1095,13 @@ static void join_workers(apr_thread_t *listener, apr_thread_t **threads) for (i = 0; i < ap_threads_per_child; i++) { if (threads[i]) { /* if we ever created this thread */ +#ifdef HAVE_PTHREAD_KILL + apr_os_thread_t *worker_os_thread; + + apr_os_thread_get(&worker_os_thread, threads[i]); + pthread_kill(*worker_os_thread, WORKER_SIGNAL); +#endif + rv = apr_thread_join(&thread_rv, threads[i]); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,