You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by dg...@hyperreal.org on 1997/11/06 11:47:03 UTC

cvs commit: apachen/src/main conf.h http_main.c

dgaudet     97/11/06 02:47:03

  Modified:    src      CHANGES
               src/main conf.h http_main.c
  Log:
  Papa Roy said I could commit this.  Fix USE_PTHREAD_SERIALIZED_ACCEPT, I
  totally didn't do it right the first time.
  
  Reviewed by:	Roy Fielding
  
  Revision  Changes    Path
  1.488     +3 -6      apachen/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/CHANGES,v
  retrieving revision 1.487
  retrieving revision 1.488
  diff -u -r1.487 -r1.488
  --- CHANGES	1997/11/06 03:03:08	1.487
  +++ CHANGES	1997/11/06 10:46:58	1.488
  @@ -1,10 +1,7 @@
   Changes with Apache 1.3b3
  -
  -  *) Restored USE_FCNTL_SERIALIZED_ACCEPT as the default for Solaris2,
  -     since the PTHREAD mechanism was losing locks on Solaris 2.5.0.
  -     You can now set -DUSE_SYSVSEM_SERIALIZED_ACCEPT or
  -     -DUSE_PTHREAD_SERIALIZED_ACCEPT in Configuration if you want to
  -     test the other two methods.  [Roy Fielding]
  +  
  +  *) Solaris >= 2.5 was totally broken due to a mess up using pthread
  +     mutexes.  [Roy Fielding, Dean Gaudet]
   
     *) OS/2 Port updated; it should be possible to build OS/2 from the same
        sources as Unix now.  [Brian Havard <br...@kheldar.apana.org.au>]
  
  
  
  1.153     +2 -2      apachen/src/main/conf.h
  
  Index: conf.h
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/main/conf.h,v
  retrieving revision 1.152
  retrieving revision 1.153
  diff -u -r1.152 -r1.153
  --- conf.h	1997/11/06 02:57:23	1.152
  +++ conf.h	1997/11/06 10:47:00	1.153
  @@ -125,8 +125,8 @@
   #define HAVE_SYS_RESOURCE_H
   #define bzero(a,b) memset(a,0,b)
   #if !defined(USE_SYSVSEM_SERIALIZED_ACCEPT) && \
  -    !defined(USE_PTHREAD_SERIALIZED_ACCEPT)
  -#define USE_FCNTL_SERIALIZED_ACCEPT
  +    !defined(USE_FCNTL_SERIALIZED_ACCEPT)
  +#define USE_PTHREAD_SERIALIZED_ACCEPT
   #endif
   #define NEED_UNION_SEMUN
   #define HAVE_MMAP
  
  
  
  1.245     +47 -3     apachen/src/main/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/main/http_main.c,v
  retrieving revision 1.244
  retrieving revision 1.245
  diff -u -r1.244 -r1.245
  --- http_main.c	1997/11/05 12:48:17	1.244
  +++ http_main.c	1997/11/06 10:47:01	1.245
  @@ -333,18 +333,33 @@
   #elif defined (USE_PTHREAD_SERIALIZED_ACCEPT)
   
   /* This code probably only works on Solaris ... but it works really fast
  - * on Solaris
  + * on Solaris.  Note that pthread mutexes are *NOT* released when a task
  + * dies ... the task has to free it itself.  So we block signals and
  + * try to be nice about releasing the mutex.
    */
   
   #include <pthread.h>
   
  -static pthread_mutex_t *accept_mutex;
  +static pthread_mutex_t *accept_mutex = (void *)(caddr_t) -1;
  +static int have_accept_mutex;
  +static sigset_t accept_block_mask;
  +static sigset_t accept_previous_mask;
  +
  +static void accept_mutex_child_cleanup(void *data)
  +{
  +    if (accept_mutex != (void *)(caddr_t)-1
  +	&& have_accept_mutex) {
  +	pthread_mutex_unlock(accept_mutex);
  +    }
  +}
   
   static void accept_mutex_cleanup(void)
   {
  -    if (munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) {
  +    if (accept_mutex != (void *)(caddr_t)-1
  +	&& munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) {
   	perror("munmap");
       }
  +    accept_mutex = (void *)(caddr_t)-1;
   }
   
   static void accept_mutex_init(pool *p)
  @@ -376,14 +391,25 @@
   	perror("pthread_mutex_init");
   	exit(1);
       }
  +    sigfillset(&accept_block_mask);
  +    sigdelset(&accept_block_mask, SIGHUP);
  +    sigdelset(&accept_block_mask, SIGTERM);
  +    sigdelset(&accept_block_mask, SIGUSR1);
  +    register_cleanup(pconf, NULL, accept_mutex_child_cleanup,
  +	accept_mutex_child_cleanup);
   }
   
   static void accept_mutex_on()
   {
  +    if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
  +	perror("sigprocmask(SIG_BLOCK)");
  +	exit (1);
  +    }
       if (pthread_mutex_lock(accept_mutex)) {
   	perror("pthread_mutex_lock");
   	exit(1);
       }
  +    have_accept_mutex = 1;
   }
   
   static void accept_mutex_off()
  @@ -391,6 +417,24 @@
       if (pthread_mutex_unlock(accept_mutex)) {
   	perror("pthread_mutex_unlock");
   	exit(1);
  +    }
  +    /* There is a slight race condition right here... if we were to die right
  +     * now, we'd do another pthread_mutex_unlock.  Now, doing that would let
  +     * another process into the mutex.  pthread mutexes are designed to be
  +     * fast, as such they don't have protection for things like testing if the
  +     * thread owning a mutex is actually unlocking it (or even any way of
  +     * testing who owns the mutex).
  +     *
  +     * If we were to unset have_accept_mutex prior to releasing the mutex
  +     * then the race could result in the server unable to serve hits.  Doing
  +     * it this way means that the server can continue, but an additional
  +     * child might be in the critical section ... at least it's still serving
  +     * hits.
  +     */
  +    have_accept_mutex = 0;
  +    if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
  +	perror("sigprocmask(SIG_SETMASK)");
  +	exit (1);
       }
   }