You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by tr...@apache.org on 2002/04/03 17:47:59 UTC
cvs commit: httpd-2.0/server/mpm/worker worker.c
trawick 02/04/03 07:47:59
Modified: . CHANGES
server/mpm/worker worker.c
Log:
worker MPM:
Don't create a listener thread until we have a worker thread. Otherwise,
in situations where we'll have to wait a while to take over scoreboard
slots from a previous generation, we'll be accepting connections we can't
process yet.
Don't let the listener thread clobber the scoreboard entry of the first
worker thread.
Revision Changes Path
1.680 +5 -0 httpd-2.0/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/httpd-2.0/CHANGES,v
retrieving revision 1.679
retrieving revision 1.680
diff -u -r1.679 -r1.680
--- CHANGES 3 Apr 2002 13:10:56 -0000 1.679
+++ CHANGES 3 Apr 2002 15:47:59 -0000 1.680
@@ -1,5 +1,10 @@
Changes with Apache 2.0.35
+ *) worker MPM: Don't create a listener thread until we have a worker
+ thread. Otherwise, in situations where we'll have to wait a while
+ to take over scoreboard slots from a previous generation, we'll be
+ accepting connections we can't process yet. [Jeff Trawick]
+
*) Allow worker MPM to build on systems without pthread_kill().
[Pier Fumagalli, Jeff Trawick]
1.111 +44 -33 httpd-2.0/server/mpm/worker/worker.c
Index: worker.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/worker/worker.c,v
retrieving revision 1.110
retrieving revision 1.111
diff -u -r1.110 -r1.111
--- worker.c 3 Apr 2002 13:10:56 -0000 1.110
+++ worker.c 3 Apr 2002 15:47:59 -0000 1.111
@@ -254,6 +254,14 @@
static void wakeup_listener(void)
{
listener_may_exit = 1;
+ if (!listener_os_thread) {
+ /* XXX there is an obscure path that this doesn't handle perfectly:
+ * right after listener thread is created but before
+ * listener_os_thread is set, the first worker thread hits an
+ * error and starts graceful termination
+ */
+ return;
+ }
/*
* we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
* platforms and wake up the listener thread since it is the only thread
@@ -655,7 +663,6 @@
{
proc_info * ti = dummy;
int process_slot = ti->pid;
- int thread_slot = ti->tid;
apr_pool_t *tpool = apr_thread_pool_get(thd);
void *csd = NULL;
apr_pool_t *ptrans; /* Pool for per-transaction stuff */
@@ -812,9 +819,6 @@
}
}
- ap_update_child_status_from_indexes(process_slot, thread_slot,
- (dying) ? SERVER_DEAD : SERVER_GRACEFUL,
- (request_rec *) NULL);
ap_queue_term(worker_queue);
dying = 1;
ap_scoreboard_image->parent[process_slot].quiescing = 1;
@@ -904,6 +908,34 @@
return 0;
}
+static void create_listener_thread(thread_starter *ts)
+{
+ int my_child_num = ts->child_num_arg;
+ apr_threadattr_t *thread_attr = ts->threadattr;
+ proc_info *my_info;
+ apr_status_t rv;
+
+ my_info = (proc_info *)malloc(sizeof(proc_info));
+ my_info->pid = my_child_num;
+ my_info->tid = -1; /* listener thread doesn't have a thread slot */
+ my_info->sd = 0;
+ rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
+ my_info, pchild);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
+ "apr_thread_create: unable to create listener thread");
+ /* In case system resources are maxxed out, we don't want
+ * Apache running away with the CPU trying to fork over and
+ * over and over again if we exit.
+ * XXX Jeff doesn't see how Apache is going to try to fork again since
+ * the exit code is APEXIT_CHILDFATAL
+ */
+ apr_sleep(10 * APR_USEC_PER_SEC);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+ apr_os_thread_get(&listener_os_thread, ts->listener);
+}
+
/* XXX under some circumstances not understood, children can get stuck
* in start_threads forever trying to take over slots which will
* never be cleaned up; for now there is an APLOG_DEBUG message issued
@@ -916,9 +948,9 @@
apr_threadattr_t *thread_attr = ts->threadattr;
int child_num_arg = ts->child_num_arg;
int my_child_num = child_num_arg;
- proc_info *my_info = NULL;
+ proc_info *my_info;
apr_status_t rv;
- int i = 0;
+ int i;
int threads_created = 0;
int loops;
int prev_threads_created;
@@ -933,33 +965,6 @@
clean_child_exit(APEXIT_CHILDFATAL);
}
- my_info = (proc_info *)malloc(sizeof(proc_info));
- my_info->pid = my_child_num;
- my_info->tid = i;
- my_info->sd = 0;
-
- /* XXX we shouldn't create the listener thread until we have at least
- * one worker thread... for now I'll blame this bug for some very
- * rare hung connections I've seen during restart testing
- * (I've also seen cases where a child process starts but is
- * never able to take over worker thread slots, so the theory
- * does make sense.) Jeff
- */
- rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
- my_info, pchild);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
- "apr_thread_create: unable to create listener thread");
- /* In case system resources are maxxed out, we don't want
- * Apache running away with the CPU trying to fork over and
- * over and over again if we exit.
- * XXX Jeff doesn't see how Apache is going to try to fork again since
- * the exit code is APEXIT_CHILDFATAL
- */
- apr_sleep(10 * APR_USEC_PER_SEC);
- clean_child_exit(APEXIT_CHILDFATAL);
- }
- apr_os_thread_get(&listener_os_thread, ts->listener);
loops = prev_threads_created = 0;
while (1) {
/* ap_threads_per_child does not include the listener thread */
@@ -998,6 +1003,12 @@
clean_child_exit(APEXIT_CHILDFATAL);
}
threads_created++;
+ if (threads_created == 1) {
+ /* now that we have a worker thread, it makes sense to create
+ * a listener thread (we don't want a listener without a worker!)
+ */
+ create_listener_thread(ts);
+ }
}
if (start_thread_may_exit || threads_created == ap_threads_per_child) {
break;