httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Paul J. Reder" <rede...@raleigh.ibm.com>
Subject [Patch]: Patch to make threaded mpm use join to cleanup workers.
Date Sat, 14 Apr 2001 19:31:02 GMT
This is the patch that I will commit if I can't find a valid reason not to.
This is an FYI heads up only. I am currently looking for any history
associated with using join in past Apache code. If I cannot find any
then I will commit this later today.

I tested this under extremely heavy load (almost 10 million requests over
a 10 hour period passing over 80 GB of data). And the server didn't have
a single problem until the machine ran out of memory (my config fault).
Actually it had run out of memory twice earlier on in the process but
recovered and continued. It finally gave up when one of the workers
returned a fatal error. But at the time the fatal error occured, there
wasn't a single orphaned thread.

The only reason performance wasn't better was related to one of the other
problems that I have pointed out (a child_main server process cannot be
replaced until it exits - even if it is left with only one or two threads
finishing their last (long) request). I will address this performance issue
in another patch.

-- 
Paul J. Reder
-----------------------------------------------------------
"The strength of the Constitution lies entirely in the determination of each
citizen to defend it.  Only if every single citizen feels duty bound to do
his share in this defense are the constitutional rights secure."
-- Albert Einstein



Index: httpd-2.0/server/mpm/threaded/threaded.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/mpm/threaded/threaded.c,v
retrieving revision 1.21
diff -u -r1.21 threaded.c
--- httpd-2.0/server/mpm/threaded/threaded.c	2001/04/12 18:46:32	1.21
+++ httpd-2.0/server/mpm/threaded/threaded.c	2001/04/14 17:51:31
@@ -544,8 +544,7 @@
         if (!workers_may_exit) {
             if ((rv = apr_accept(&csd, sd, ptrans)) != APR_SUCCESS) {
                 csd = NULL;
-                ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, 
-                             "apr_accept");
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "apr_accept");
             }
             if ((rv = SAFE_ACCEPT(apr_lock_release(accept_mutex)))
                 != APR_SUCCESS) {
@@ -573,8 +572,7 @@
     }
 
     apr_pool_destroy(tpool);
-    ap_update_child_status(process_slot, thread_slot, SERVER_DEAD,
-        (request_rec *) NULL);
+    ap_update_child_status(process_slot, thread_slot, SERVER_DEAD, (request_rec *) NULL);
     apr_lock_acquire(worker_thread_count_mutex);
     worker_thread_count--;
     if (worker_thread_count == 0) {
@@ -592,15 +590,14 @@
     switch (signum) {
         case SIGTERM:
         case SIGINT:
-            just_die(signum);
             return 1;
-    }                                                                           
+    }      
     return 0;
 }
 
 static void child_main(int child_num_arg)
 {
-    apr_thread_t *thread;
+    apr_thread_t **threads;
     apr_threadattr_t *thread_attr;
     int i;
     int my_child_num = child_num_arg;
@@ -650,13 +647,20 @@
 	listensocks[i]=lr->sd;
 
     /* Setup worker threads */
+
+    threads = (apr_thread_t **)malloc(sizeof(apr_thread_t *) * ap_threads_per_child);
+    if (threads == NULL) {
+        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
+                     "malloc: out of memory");
+        clean_child_exit(APEXIT_CHILDFATAL);
+    }
     worker_thread_count = 0;
     apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
                     NULL, pchild);
     apr_lock_create(&pipe_of_death_mutex, APR_MUTEX, APR_INTRAPROCESS, 
                     NULL, pchild);
     apr_threadattr_create(&thread_attr, pchild);
-    apr_threadattr_detach_set(thread_attr, 1);
+    apr_threadattr_detach_set(thread_attr, PTHREAD_CREATE_JOINABLE);
 
     for (i=0; i < ap_threads_per_child; i++) {
 
@@ -674,7 +678,7 @@
 	/* We are creating threads right now */
 	(void) ap_update_child_status(my_child_num, i, SERVER_STARTING, 
 				      (request_rec *) NULL);
-	if ((rv = apr_thread_create(&thread, thread_attr, worker_thread, my_info, pchild)))
{
+	if ((rv = apr_thread_create(&threads[i], thread_attr, worker_thread, my_info, pchild)))
{
 	    ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
 			 "apr_thread_create: unable to create worker thread");
             /* In case system resources are maxxed out, we don't want
@@ -687,7 +691,23 @@
 	 * because it let's us deal with tid better.
 	 */
     }
+    
+    /* What state should this child_main process be listed as in the scoreboard...?
+    ap_update_child_status(my_child_num, i, SERVER_STARTING, (request_rec *) NULL);
+    */
+
     apr_signal_thread(check_signal);
+
+    /* A terminating signal was received. Now join each of the workers to clean them up.
*/
+    /*   If the worker already exitted, then the join frees their resources and returns.
*/
+    /*   If the worker hasn't exited, then this blocks until they have (then cleans up).
*/
+    for (i = 0; i < ap_threads_per_child; i++) {
+        apr_thread_join(&rv, threads[i]);
+    }
+
+    free (threads);
+
+    clean_child_exit(0);
 }
 
 static int make_child(server_rec *s, int slot)

Mime
View raw message