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/03/27 21:37:32 UTC

cvs commit: httpd-2.0/server/mpm/worker pod.c worker.c

trawick     02/03/27 12:37:32

  Modified:    .        CHANGES
               server/mpm/worker pod.c worker.c
  Log:
  worker MPM:
  
  get MaxRequestsPerChild to work again by allowing the main thread of
  a child to be interrupted by one of the other threads in the process
  
  this should get graceful termination to work after encountering one of
  the various possible error conditions in the listener and worker threads
  
  Revision  Changes    Path
  1.662     +2 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.661
  retrieving revision 1.662
  diff -u -r1.661 -r1.662
  --- CHANGES	27 Mar 2002 14:24:32 -0000	1.661
  +++ CHANGES	27 Mar 2002 20:37:31 -0000	1.662
  @@ -1,5 +1,7 @@
   Changes with Apache 2.0.35
   
  +  *) worker MPM: Get MaxRequestsPerChild to work again.  [Jeff Trawick]
  +
     *) [APR-related] The ordering of the default accept mutex method has
        been changed to better match what's done in Apache 1.3. The ordering 
        is now (highest to lowest): pthread -> sysvsem -> fcntl -> flock.
  
  
  
  1.5       +14 -11    httpd-2.0/server/mpm/worker/pod.c
  
  Index: pod.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/worker/pod.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- pod.c	20 Mar 2002 03:54:25 -0000	1.4
  +++ pod.c	27 Mar 2002 20:37:32 -0000	1.5
  @@ -72,6 +72,9 @@
   #include "ap_mpm.h"
   #include "ap_listen.h"
   #include "mpm_default.h"
  +#if APR_HAVE_UNISTD_H
  +#include <unistd.h>
  +#endif
   
   AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod)
   {
  @@ -93,21 +96,21 @@
   AP_DECLARE(int) ap_mpm_pod_check(ap_pod_t *pod)
   {
       char c;
  -    apr_size_t len = 1;
  -    apr_status_t rv;
  -
  -    rv = apr_file_read(pod->pod_in, &c, &len);
  +    apr_os_file_t fd;
  +    int rc;
   
  -    if ((rv == APR_SUCCESS) && (len ==1)) {
  -        if (c == RESTART_CHAR) {
  +    /* we need to surface EINTR so we'll have to grab the
  +     * native file descriptor and do the OS read() ourselves
  +     */
  +    apr_os_file_get(&fd, pod->pod_in);
  +    rc = read(fd, &c, 1);
  +    if (rc == 1) {
  +        switch(c) {
  +        case RESTART_CHAR:
               return AP_RESTART;
  -        }
  -        if (c == GRACEFUL_CHAR) {
  +        case GRACEFUL_CHAR:
               return AP_GRACEFUL;
           }
  -    }
  -    else if (rv != APR_SUCCESS) {
  -        return rv;
       }
       return AP_NORESTART;
   }
  
  
  
  1.107     +39 -26    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.106
  retrieving revision 1.107
  diff -u -r1.106 -r1.107
  --- worker.c	22 Mar 2002 03:43:22 -0000	1.106
  +++ worker.c	27 Mar 2002 20:37:32 -0000	1.107
  @@ -262,17 +262,18 @@
       pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
   }
   
  +#define ST_INIT              0
   #define ST_GRACEFUL          1
   #define ST_UNGRACEFUL        2
   
  +static int terminate_mode = ST_INIT;
  +
   static void signal_threads(int mode)
   {
  -    static int prev_mode = 0;
  -    
  -    if (prev_mode == mode) {
  +    if (terminate_mode == mode) {
           return;
       }
  -    prev_mode = mode;
  +    terminate_mode = mode;
   
       /* in case we weren't called from the listener thread, wake up the
        * listener thread
  @@ -625,7 +626,20 @@
       }
   }
   
  -static void unblock_the_listener(int sig)
  +static void unblock_signal(int sig)
  +{
  +    sigset_t sig_mask;
  +
  +    sigemptyset(&sig_mask);
  +    sigaddset(&sig_mask, sig);
  +#if defined(SIGPROCMASK_SETS_THREAD_MASK)
  +    sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
  +#else
  +    pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
  +#endif
  +}
  +
  +static void dummy_signal_handler(int sig)
   {
       /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
        *     then we don't need this goofy function.
  @@ -645,8 +659,6 @@
       apr_pollfd_t *pollset;
       apr_status_t rv;
       ap_listen_rec *lr, *last_lr = ap_listeners;
  -    struct sigaction sa;
  -    sigset_t sig_mask;
   
       free(ti);
   
  @@ -654,20 +666,11 @@
       for(lr = ap_listeners ; lr != NULL ; lr = lr->next)
           apr_poll_socket_add(pollset, lr->sd, APR_POLLIN);
   
  -    sigemptyset(&sig_mask);
       /* Unblock the signal used to wake this thread up, and set a handler for
        * it.
        */
  -    sigaddset(&sig_mask, LISTENER_SIGNAL);
  -#if defined(SIGPROCMASK_SETS_THREAD_MASK)
  -    sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
  -#else
  -    pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
  -#endif
  -    sigemptyset(&sa.sa_mask);
  -    sa.sa_flags = 0;
  -    sa.sa_handler = unblock_the_listener;
  -    sigaction(LISTENER_SIGNAL, &sa, NULL);
  +    unblock_signal(LISTENER_SIGNAL);
  +    apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
   
       /* TODO: Switch to a system where threads reuse the results from earlier
          poll calls - manoj */
  @@ -811,10 +814,7 @@
       dying = 1;
       ap_scoreboard_image->parent[process_slot].quiescing = 1;
   
  -    /* XXX in one-process mode, this SIGTERM will wake up the main thread
  -     *     in normal mode, it is unclear what it will do... the main
  -     *     thread is stuck in a read on the POD
  -     */
  +    /* wake up the main thread */
       kill(ap_my_pid, SIGTERM);
   
       apr_thread_exit(thd, APR_SUCCESS);
  @@ -1196,13 +1196,26 @@
           join_workers(ts->listener, threads);
       }
       else { /* !one_process */
  +        /* remove SIGTERM from the set of blocked signals...  if one of
  +         * the other threads in the process needs to take us down
  +         * (e.g., for MaxRequestsPerChild) it will send us SIGTERM
  +         */
  +        unblock_signal(SIGTERM);
  +        apr_signal(SIGTERM, dummy_signal_handler);
           /* Watch for any messages from the parent over the POD */
           while (1) {
  -            /* XXX join_start_thread() won't be awakened if one of our
  -             *     threads encounters a critical error and attempts to
  -             *     shutdown this child
  -             */
               rv = ap_mpm_pod_check(pod);
  +            if (rv == AP_NORESTART) {
  +                /* see if termination was triggered while we slept */
  +                switch(terminate_mode) {
  +                case ST_GRACEFUL:
  +                    rv = AP_GRACEFUL;
  +                    break;
  +                case ST_UNGRACEFUL:
  +                    rv = AP_RESTART;
  +                    break;
  +                }
  +            }
               if (rv == AP_GRACEFUL || rv == AP_RESTART) {
                   /* make sure the start thread has finished; 
                    * signal_threads() and join_workers depend on that