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;