From: Greg Ames Date: Wed, 16 Sep 2009 18:07:09 +0000 (+0000) Subject: * prevent a fork bomb if the accept mutex is clobbered by exiting with X-Git-Tag: 2.3.3~286 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=201d3d584faffd2c7f7f02bbf16c02a95b5759e5;p=apache * prevent a fork bomb if the accept mutex is clobbered by exiting with APEXIT_CHILDSICK if the worker process hasn't served any requests * move the accept mutex error leg into its own function to take advantage of common code and to keep rarely executed instructions out of the mainline instruction cache. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@815915 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index d1ae528254..92b26fe455 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -595,6 +595,29 @@ static void dummy_signal_handler(int sig) */ } +static void accept_mutex_error(char *func, apr_status_t rv, int process_slot) +{ + int level = APLOG_EMERG; + + if (ap_scoreboard_image->parent[process_slot].generation != + ap_scoreboard_image->global->running_generation) { + level = APLOG_DEBUG; /* common to get these at restart time */ + } + else if (requests_this_child == INT_MAX + || ((requests_this_child == ap_max_requests_per_child) + && ap_max_requests_per_child)) { + ap_log_error(APLOG_MARK, level, rv, ap_server_conf, + "apr_proc_mutex_%s failed " + "before this child process served any requests.", + func); + clean_child_exit(APEXIT_CHILDSICK); + } + ap_log_error(APLOG_MARK, level, rv, ap_server_conf, + "apr_proc_mutex_%s failed. Attempting to " + "shutdown process gracefully.", func); + signal_threads(ST_GRACEFUL); +} + static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy) { proc_info * ti = dummy; @@ -678,19 +701,10 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy) if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex))) != APR_SUCCESS) { - int level = APLOG_EMERG; - if (listener_may_exit) { - break; + if (!listener_may_exit) { + accept_mutex_error("lock", rv, process_slot); } - if (ap_scoreboard_image->parent[process_slot].generation != - ap_scoreboard_image->global->running_generation) { - level = APLOG_DEBUG; /* common to get these at restart time */ - } - ap_log_error(APLOG_MARK, level, rv, ap_server_conf, - "apr_proc_mutex_lock failed. Attempting to shutdown " - "process gracefully."); - signal_threads(ST_GRACEFUL); break; /* skip the lock release */ } @@ -769,19 +783,11 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy) } if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex))) != APR_SUCCESS) { - int level = APLOG_EMERG; if (listener_may_exit) { break; } - if (ap_scoreboard_image->parent[process_slot].generation != - ap_scoreboard_image->global->running_generation) { - level = APLOG_DEBUG; /* common to get these at restart time */ - } - ap_log_error(APLOG_MARK, level, rv, ap_server_conf, - "apr_proc_mutex_unlock failed. Attempting to " - "shutdown process gracefully."); - signal_threads(ST_GRACEFUL); + accept_mutex_error("unlock", rv, process_slot); } if (csd != NULL) { rv = ap_queue_push(worker_queue, csd, ptrans);