httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Justin Erenkrantz <jerenkra...@ebuilt.com>
Subject Re: [PATCH] POD and Threaded MPM...
Date Wed, 11 Jul 2001 17:05:39 GMT
On Wed, Jul 11, 2001 at 07:44:14AM -0700, rbb@covalent.net wrote:
> 
> The threaded MPM should use the POD calls from mpm_common.c, but they were
> added after the threaded MPM was written, and I never bothered to port
> it when I wrote the pod code.
> 
> Ryan

Completely untested.  Well, it compiles.  

The only disadvantage is that since we aren't doing a select on the pod,
we have to check every time, but now that check isn't an exclusive 
operation.  So, it's probably a win just for that reason.  =)  

Since the mpm_common.c code has the correct call to file_read (i.e.
checks the return length), this should fix the problem with threaded 
children dying too quickly.  But, I can't reproduce it anyway, so it's
all theoretical from here.  Someone who has this problem should see if
this fixes it.  I bet it will.  -- justin

Index: server/mpm/threaded/mpm.h
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/threaded/mpm.h,v
retrieving revision 1.5
diff -u -r1.5 mpm.h
--- server/mpm/threaded/mpm.h	2001/05/07 18:41:48	1.5
+++ server/mpm/threaded/mpm.h	2001/07/11 17:01:18
@@ -66,6 +66,7 @@
 #define MPM_NAME "Threaded"
 
 #define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
+#define AP_MPM_USES_POD 1
 #define MPM_SYNC_CHILD_TABLE() (ap_sync_scoreboard_image())
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
 #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
Index: server/mpm/threaded/threaded.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/threaded/threaded.c,v
retrieving revision 1.44
diff -u -r1.44 threaded.c
--- server/mpm/threaded/threaded.c	2001/07/03 13:58:10	1.44
+++ server/mpm/threaded/threaded.c	2001/07/11 17:01:19
@@ -143,10 +143,7 @@
 
 char ap_coredump_dir[MAX_STRING_LEN];
 
-static apr_file_t *pipe_of_death_in = NULL;
-static apr_file_t *pipe_of_death_out = NULL;
-static apr_lock_t *pipe_of_death_mutex;   /* insures that a child process only
-                                             consumes one character */
+static ap_pod_t *pipe_of_death;
 
 /* *Non*-shared http_main globals... */
 
@@ -494,29 +491,6 @@
     }
 }
 
-/* Sets workers_may_exit if we received a character on the pipe_of_death */
-static void check_pipe_of_death(void)
-{
-    apr_lock_acquire(pipe_of_death_mutex);
-    if (!workers_may_exit) {
-        apr_status_t ret;
-        char pipe_read_char;
-	apr_size_t n = 1;
-
-        ret = apr_recv(listensocks[0], &pipe_read_char, &n);
-        if (APR_STATUS_IS_EAGAIN(ret)) {
-            /* It lost the lottery. It must continue to suffer
-             * through a life of servitude. */
-        }
-        else {
-            /* It won the lottery (or something else is very
-             * wrong). Embrace death with open arms. */
-            workers_may_exit = 1;
-        }
-    }
-    apr_lock_release(pipe_of_death_mutex);
-}
-
 static void * worker_thread(void * dummy)
 {
     proc_info * ti = dummy;
@@ -539,8 +513,8 @@
     worker_thread_count++;
     apr_lock_release(worker_thread_count_mutex);
 
-    apr_poll_setup(&pollset, num_listensocks+1, tpool);
-    for(n=0 ; n <= num_listensocks ; ++n)
+    apr_poll_setup(&pollset, num_listensocks, tpool);
+    for(n = 0; n < num_listensocks; ++n)
 	apr_poll_socket_add(pollset, listensocks[n], APR_POLLIN);
 
     /* TODO: Switch to a system where threads reuse the results from earlier
@@ -580,12 +554,8 @@
 
             if (workers_may_exit) break;
 
-	    apr_poll_revents_get(&event, listensocks[0], pollset);
-            if (event & APR_POLLIN) {
-                /* A process got a signal on the shutdown pipe. Check if we're
-                 * the lucky process to die. */
-                check_pipe_of_death();
-                continue;
+            if (!ap_mpm_pod_check(pipe_of_death)) {
+                workers_may_exit = 1;
             }
 
             if (num_listensocks == 1) {
@@ -780,12 +750,8 @@
     }
     
     /* Set up the pollfd array */
-    listensocks = apr_pcalloc(pchild,
-			    sizeof(*listensocks) * (num_listensocks + 1));
-#if APR_FILES_AS_SOCKETS
-    apr_socket_from_file(&listensocks[0], pipe_of_death_in);
-#endif
-    for (lr = ap_listeners, i = 1; i <= num_listensocks; lr = lr->next, ++i)
+    listensocks = apr_pcalloc(pchild, sizeof(*listensocks) * num_listensocks);
+    for (lr = ap_listeners, i = 0; i < num_listensocks; lr = lr->next, ++i)
 	listensocks[i]=lr->sd;
 
     /* Setup worker threads */
@@ -799,8 +765,6 @@
     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);
 
     ts = apr_palloc(pchild, sizeof(*ts));
 
@@ -894,29 +858,6 @@
     return 0;
 }
 
-/* If there aren't many connections coming in from the network, the child 
- * processes may need to be awakened from their network i/o waits.
- * The pipe of death is an effective prod.
- */
-   
-static void wake_up_and_die(void) 
-{
-    int i;
-    char char_of_death = '!';
-    apr_size_t one = 1;
-    apr_status_t rv;
-    
-    for (i = 0; i < ap_daemons_limit;) {
-        if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) 
-                                 != APR_SUCCESS) {
-            if (APR_STATUS_IS_EINTR(rv)) continue;
-            ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, 
-                         "write pipe_of_death");
-        }
-        i++;
-    }
-}
-
 /* start up a bunch of children */
 static void startup_children(int number_to_start)
 {
@@ -955,8 +896,6 @@
     int free_slots[MAX_SPAWN_RATE];
     int last_non_dead;
     int total_non_dead;
-    apr_size_t one = 1;
-    apr_status_t rv;
 
     /* initialize the free_list */
     free_length = 0;
@@ -1004,11 +943,7 @@
     ap_max_daemons_limit = last_non_dead + 1;
 
     if (idle_thread_count > max_spare_threads) {
-        char char_of_death = '!';
-        /* Kill off one child */
-        if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS)
{
-            ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, "write pipe_of_death");
-        }
+        ap_mpm_pod_signal(pipe_of_death);
         idle_spawn_rate = 1;
     }
     else if (idle_thread_count < min_spare_threads) {
@@ -1129,18 +1064,11 @@
     pconf = _pconf;
     ap_server_conf = s;
 
-    rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out, pconf);
+    rv = ap_mpm_pod_open(pconf, &pipe_of_death);
     if (rv != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, rv,
-                     (const server_rec*) ap_server_conf,
-                     "apr_file_pipe_create (pipe_of_death)");
-        exit(1);
-    }
-
-    if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv,
                      (const server_rec*) ap_server_conf,
-                     "apr_file_pipe_timeout_set (pipe_of_death)");
+                     "ap_mpm_pod_open");
         exit(1);
     }
 
@@ -1208,7 +1136,7 @@
         /* Time to gracefully shut down:
          * Kill child processes, tell them to call child_exit, etc...
          */
-        wake_up_and_die();
+        ap_mpm_pod_killpg(pipe_of_death, ap_daemons_limit);
 
         if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
@@ -1249,7 +1177,7 @@
     update_scoreboard_global();
     
     /* wake up the children...time to die.  But we'll have more soon */
-    wake_up_and_die();
+    ap_mpm_pod_killpg(pipe_of_death, ap_daemons_limit);
     
     if (is_graceful) {
 	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,


Mime
View raw message