From 3fcd09b25470c2a28fbba57e4492c72b8ce8c3ee Mon Sep 17 00:00:00 2001 From: Jeff Trawick Date: Sun, 24 Feb 2002 20:53:26 +0000 Subject: [PATCH] restart fixes for worker: fix a segfault and a window in which we could miss joining newly-created threads we can't try to signal workers if the worker queue hasn't been initialized (or we segfault) make sure the start thread is done creating threads before we try to join; otherwise we can just miss some of them and not be able to clean them up properly git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93561 13f79535-47bb-0310-9956-ffa450edef68 --- server/mpm/worker/worker.c | 54 ++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index 61a63ae436..baa8ed159a 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -885,10 +885,39 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy) return NULL; } +static void join_workers(apr_thread_t **threads) +{ + int i; + apr_status_t rv, thread_rv; + + for (i = 0; i < ap_threads_per_child; i++) { + if (threads[i]) { /* if we ever created this thread */ + rv = apr_thread_join(&thread_rv, threads[i]); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, + "apr_thread_join: unable to join worker " + "thread %d", + i); + } + } + } +} + +static void join_start_thread(apr_thread_t *start_thread_id) +{ + apr_status_t rv, thread_rv; + + rv = apr_thread_join(&thread_rv, start_thread_id); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, + "apr_thread_join: unable to join the start " + "thread"); + } +} + static void child_main(int child_num_arg) { apr_thread_t **threads; - int i; apr_status_t rv; thread_starter *ts; apr_threadattr_t *thread_attr; @@ -961,7 +990,6 @@ static void child_main(int child_num_arg) ts->child_num_arg = child_num_arg; ts->threadattr = thread_attr; - rv = apr_thread_create(&start_thread_id, thread_attr, start_threads, ts, pchild); if (rv != APR_SUCCESS) { @@ -979,6 +1007,10 @@ static void child_main(int child_num_arg) if (one_process) { /* Set up a signal handler for this thread. */ apr_signal_thread(check_signal); + /* make sure the start thread has finished; signal_workers() + * and join_workers() depend on that + */ + join_start_thread(start_thread_id); signal_workers(); /* helps us terminate a little more quickly when * the dispatch of the signal thread * beats the Pipe of Death and the browsers @@ -990,18 +1022,17 @@ static void child_main(int child_num_arg) * If the worker hasn't exited, then this blocks until * they have (then cleans up). */ - apr_thread_join(&rv, start_thread_id); - for (i = 0; i < ap_threads_per_child; i++) { - if (threads[i]) { /* if we ever created this thread */ - apr_thread_join(&rv, threads[i]); - } - } + join_workers(threads); } else { /* !one_process */ /* Watch for any messages from the parent over the POD */ while (1) { rv = ap_mpm_pod_check(pod); if (rv == AP_GRACEFUL || rv == AP_RESTART) { + /* make sure the start thread has finished; + * signal_workers() and join_workers depend on that + */ + join_start_thread(start_thread_id); signal_workers(); break; } @@ -1015,12 +1046,7 @@ static void child_main(int child_num_arg) * If the worker hasn't exited, then this blocks until * they have (then cleans up). */ - apr_thread_join(&rv, start_thread_id); - for (i = 0; i < ap_threads_per_child; i++) { - if (threads[i]) { /* if we ever created this thread */ - apr_thread_join(&rv, threads[i]); - } - } + join_workers(threads); } } -- 2.50.1