From: Greg Ames Date: Sat, 28 Jul 2001 23:39:07 +0000 (+0000) Subject: Fix a problem where the threaded MPM stalls after restarts or segfaults. X-Git-Tag: 2.0.23~165 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96408397d3dc826d0641aaf841f6f88da3a16d81;p=thirdparty%2Fapache%2Fhttpd.git Fix a problem where the threaded MPM stalls after restarts or segfaults. Also prevent multiple active processes from using the same scoreboard slot. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@89761 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 3dae5c0a716..825886538ac 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,10 @@ Changes with Apache 2.0.23 Transitional specifications. [William Rowe] Changes with Apache 2.0.22 + + *) Fix a problem where the threaded MPM stalls after restarts or + segfaults. Also prevent multiple active processes from using + the same scoreboard slot. [Greg Ames] *) Apache/Win32 now fills in the service description with Apache's server version string, including loaded and advertised modules. diff --git a/include/scoreboard.h b/include/scoreboard.h index 2f6c32c9f82..675ffe9b3d5 100644 --- a/include/scoreboard.h +++ b/include/scoreboard.h @@ -178,6 +178,9 @@ struct process_score{ pid_t pid; ap_generation_t generation; /* generation of this child */ ap_scoreboard_e sb_type; + int quiescing; /* the process whose pid is stored above is + * going down gracefully + */ }; typedef struct { diff --git a/server/mpm/threaded/threaded.c b/server/mpm/threaded/threaded.c index dccc9f46d32..15c19dad39f 100644 --- a/server/mpm/threaded/threaded.c +++ b/server/mpm/threaded/threaded.c @@ -648,8 +648,15 @@ static void * worker_thread(apr_thread_t *thd, void * dummy) apr_pool_destroy(tpool); ap_update_child_status(process_slot, thread_slot, (dying) ? SERVER_DEAD : SERVER_GRACEFUL, (request_rec *) NULL); - dying = 1; apr_lock_acquire(worker_thread_count_mutex); + if (!dying) { + /* this is the first thread to exit */ + if (ap_my_pid == ap_scoreboard_image->parent[process_slot].pid) { + /* tell the parent that it may use this scoreboard slot */ + ap_scoreboard_image->parent[process_slot].quiescing = 1; + } + dying = 1; + } worker_thread_count--; if (worker_thread_count == 0) { /* All the threads have exited, now finish the shutdown process @@ -900,6 +907,7 @@ static int make_child(server_rec *s, int slot) clean_child_exit(0); } /* else */ + ap_scoreboard_image->parent[slot].quiescing = 0; ap_scoreboard_image->parent[slot].pid = pid; return 0; } @@ -961,6 +969,7 @@ static void perform_idle_server_maintenance(void) int i, j; int idle_thread_count; worker_score *ws; + process_score *ps; int free_length; int free_slots[MAX_SPAWN_RATE]; int last_non_dead; @@ -985,6 +994,7 @@ static void perform_idle_server_maintenance(void) if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate) break; + ps = &ap_scoreboard_image->parent[i]; for (j = 0; j < ap_threads_per_child; j++) { ws = &ap_scoreboard_image->servers[i][j]; status = ws->status; @@ -998,11 +1008,19 @@ static void perform_idle_server_maintenance(void) * So we hopefully won't need to fork more if we count it. * This depends on the ordering of SERVER_READY and SERVER_STARTING. */ - if (status <= SERVER_READY && status != SERVER_DEAD) { + if (status <= SERVER_READY && status != SERVER_DEAD && + ps->generation == ap_my_generation && + /* XXX the following shouldn't be necessary if we clean up + * properly after seg faults, but we're not yet GLA + */ + ps->pid != 0) { ++idle_thread_count; } } - if (any_dead_threads && free_length < idle_spawn_rate) { + /* XXX any_dead_threads may not be needed any more GLA */ + if (any_dead_threads && free_length < idle_spawn_rate + && (!ps->pid /* no process in the slot */ + || ps->quiescing)) { /* or at least one is going away */ free_slots[free_length] = i; ++free_length; } @@ -1083,6 +1101,8 @@ static void server_main_loop(int remaining_children_to_start) for (i = 0; i < ap_threads_per_child; i++) ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL); + ap_scoreboard_image->parent[child_slot].pid = 0; + ap_scoreboard_image->parent[child_slot].quiescing = 0; if (remaining_children_to_start && child_slot < ap_daemons_limit) { /* we're still doing a 1-for-1 replacement of dead