You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rb...@hyperreal.org on 1999/02/03 18:50:15 UTC

cvs commit: apache-apr/pthreads/src/os/unix multithread.c

rbb         99/02/03 09:50:15

  Modified:    pthreads/src/main Makefile.tmpl alloc.c http_main.c
               pthreads/src/modules/standard mod_autoindex.c
               pthreads/src/os/unix multithread.c
  Added:       pthreads/src/include fdqueue.h
               pthreads/src/main fdqueue.c
  Log:
  Port to hybrid process/thread model.  Doesn't work fully, but it will serve one request before dying.  Basically the process that serves the first request becomes a zombie, so the subsequent requests are never picked up off the fd queue.
  Submitted by: fdqueue.[ch] submitted by Manoj KAsichainula
  
  Revision  Changes    Path
  1.1                  apache-apr/pthreads/src/include/fdqueue.h
  
  Index: fdqueue.h
  ===================================================================
  #ifndef FDQUEUE_H
  #define FDQUEUE_H
  #include <stdlib.h>
  #include <unistd.h>
  #include <pthread.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  
  /* Bleccch. 0 on success always rubbed me the wrong way */
  /* All failures are unrecoverable */
  #define FD_QUEUE_SUCCESS 0
  #define FD_QUEUE_FAILURE -1 /* Needs to be an invalid file descriptor because
                                 of queue_pop semantics */
  
  typedef struct fd_queue_elem {
      int fd;
      struct sockaddr addr;
  } FDQueueElement;
  
  typedef struct fd_queue {
      int head;
      int tail;
      FDQueueElement *data;
      int bounds;
      pthread_mutex_t one_big_mutex;
      pthread_cond_t not_empty;
      pthread_cond_t not_full;
  } FDQueue;
  
  int queue_init(FDQueue *queue, size_t bounds);
  void queue_destroy(FDQueue *queue);
  int queue_push(FDQueue *queue, int fd, struct sockaddr *addr);
  int queue_pop(FDQueue *queue, struct sockaddr *addr);
  int queue_size(FDQueue *queue);
  
  #endif /* FDQUEUE_H */
  
  
  
  1.2       +1 -1      apache-apr/pthreads/src/main/Makefile.tmpl
  
  Index: Makefile.tmpl
  ===================================================================
  RCS file: /home/cvs/apache-apr/pthreads/src/main/Makefile.tmpl,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Makefile.tmpl	1999/01/21 23:08:32	1.1
  +++ Makefile.tmpl	1999/02/03 17:50:08	1.2
  @@ -11,7 +11,7 @@
         http_config.o http_core.o http_log.o \
         http_main.o http_protocol.o http_request.o http_vhost.o \
         util.o util_date.o util_script.o util_uri.o util_md5.o \
  -      md5c.o rfc1413.o
  +      md5c.o rfc1413.o fdqueue.o
   
   .c.o:
   	$(CC) -c $(INCLUDES) $(CFLAGS) $<
  
  
  
  1.2       +7 -7      apache-apr/pthreads/src/main/alloc.c
  
  Index: alloc.c
  ===================================================================
  RCS file: /home/cvs/apache-apr/pthreads/src/main/alloc.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- alloc.c	1999/01/21 23:08:32	1.1
  +++ alloc.c	1999/02/03 17:50:09	1.2
  @@ -1975,14 +1975,14 @@
   	if (pipe_in) {
   	    close(in_fds[0]);
   	    close(in_fds[1]);
  -	}
  +	    }
   	if (pipe_out) {
   	    close(out_fds[0]);
   	    close(out_fds[1]);
  -	}
  +      	}
   	errno = save_errno;
   	return 0;
  -    }
  +	}
   
   #ifdef WIN32
   
  @@ -2077,10 +2077,10 @@
   	    close(out_fds[0]);
   	    close(out_fds[1]);
   	}
  -	if (pipe_err) {
  +      	if (pipe_err) {
   	    close(err_fds[0]);
   	    close(err_fds[1]);
  -	}
  +	    }
   	errno = save_errno;
   	return 0;
       }
  @@ -2101,11 +2101,11 @@
   	    close(in_fds[0]);
   	}
   
  -	if (pipe_err) {
  +       	if (pipe_err) {
   	    close(err_fds[0]);
   	    dup2(err_fds[1], STDERR_FILENO);
   	    close(err_fds[1]);
  -	}
  +	    }
   
   	/* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */
   	signal(SIGCHLD, SIG_DFL);	/* Was that it? */
  
  
  
  1.5       +272 -157  apache-apr/pthreads/src/main/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /home/cvs/apache-apr/pthreads/src/main/http_main.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- http_main.c	1999/01/28 21:54:07	1.4
  +++ http_main.c	1999/02/03 17:50:09	1.5
  @@ -92,9 +92,16 @@
   #include "util_script.h"	/* to force util_script.c linking */ 
   #include "util_uri.h" 
   #include "scoreboard.h" 
  +#include "fdqueue.h" 
   #include <poll.h> 
   #include <netinet/tcp.h> 
   #include <stdio.h> 
  +
  +#ifdef USE_SHMGET_SCOREBOARD
  +#include <sys/types.h>
  +#include <sys/ipc.h>
  +#include <sys/shm.h>
  +#endif
    
   #include "pthread.h" 
   /*#include initialization if any 
  @@ -149,7 +156,7 @@
   #ifdef MULTIPLE_GROUPS
   gid_t group_id_list[NGROUPS_MAX];
   #endif
  -int ap_threads_per_child;
  +int ap_threads_per_child = 5; /* Need to require this directive, or make a valid default */
   int ap_excess_requests_per_child;
   char *ap_pid_fname;
   char *ap_scoreboard_fname;
  @@ -199,16 +206,14 @@
   array_header *ap_server_pre_read_config;
   array_header *ap_server_post_read_config;
   array_header *ap_server_config_defines;
  +pool *pchild;		/* Pool for httpd child stuff */
  +
  +/* The queue of sockets we've accepted */
  +static FDQueue csd_queue;
   
   /* stuff that needs thread local store in main */
   typedef struct {
  -
  -
  -
       jmp_buf thread_exit;
  -    pool *pchild;		/* Pool for httpd child stuff */
  -    int my_child_num;
  -    int requests_this_child;
       int generation;
   } tls_main_t;
   
  @@ -230,7 +235,6 @@
   
   
   /* used by accept_loop(), which is serialized */
  -static pthread_mutex_t accept_loop_lock; /* Replace AcceptLoopLock with abstract type */
   static listen_rec *head_listener;
   
   /* *Non*-shared http_main globals... */
  @@ -274,10 +278,11 @@
   static pool *ptemp;		/* Pool for temporart config stuff */
   static pool *pcommands;	/* Pool for -C and -c switches */
   
  -scoreboard *ap_scoreboard_image = NULL;
  +static int my_pid; /* for hybridization, we need this.  Stupid to
  +				 call getpid all the time */
  +static int requests_this_child;
   
  -
  -
  +scoreboard *ap_scoreboard_image = NULL;
   
   /*
    * Pieces for managing the contents of the Server response header
  @@ -306,6 +311,101 @@
       return (server_version ? server_version : SERVER_BASEVERSION);
   }
   
  +#if defined(USE_SHMGET_SCOREBOARD)
  +static key_t shmkey = IPC_PRIVATE;
  +static int shmid = -1;
  +
  +static void setup_shared_mem(pool *p)
  +{
  +    struct shmid_ds shmbuf;
  +#ifdef MOVEBREAK
  +    char *obrk;
  +#endif
  +
  +    if ((shmid = shmget(shmkey, SCOREBOARD_SIZE, IPC_CREAT | SHM_R | SHM_W)) ==
  +-1) {
  +#ifdef LINUX
  +        if (errno == ENOSYS) {
  +            ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
  +                         "Your kernel was built without CONFIG_SYSVIPC\n"
  +                         "%s: Please consult the Apache FAQ for details",
  +                         ap_server_argv0);
  +        }
  +#endif
  +        ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  +                    "could not call shmget");
  +        exit(APEXIT_INIT);
  +    }
  +
  +    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
  +                "created shared memory segment #%d", shmid);
  +
  +#ifdef MOVEBREAK
  +    /*
  +     * Some SysV systems place the shared segment WAY too close
  +     * to the dynamic memory break point (sbrk(0)). This severely
  +     * limits the use of malloc/sbrk in the program since sbrk will
  +     * refuse to move past that point.
  +     *
  +     * To get around this, we move the break point "way up there",
  +     * attach the segment and then move break back down. Ugly
  +     */
  +    if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) {
  +        ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  +            "sbrk() could not move break");
  +    }
  +#endif
  +
  +#define BADSHMAT        ((scoreboard *)(-1))
  +    if ((ap_scoreboard_image = (scoreboard *) shmat(shmid, 0, 0)) == BADSHMAT) {
  +        ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "shmat error");
  +        /*
  +         * We exit below, after we try to remove the segment
  +         */
  +    }
  +    else {                      /* only worry about permissions if we attached t
  +he segment */
  +        if (shmctl(shmid, IPC_STAT, &shmbuf) != 0) {
  +            ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  +                "shmctl() could not stat segment #%d", shmid);
  +        }
  +        else {
  +            shmbuf.shm_perm.uid = ap_user_id;
  +            shmbuf.shm_perm.gid = ap_group_id;
  +            if (shmctl(shmid, IPC_SET, &shmbuf) != 0) {
  +                ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  +                    "shmctl() could not set segment #%d", shmid);
  +            }
  +        }
  +    }
  +    /*
  +     * We must avoid leaving segments in the kernel's
  +     * (small) tables.
  +     */
  +    if (shmctl(shmid, IPC_RMID, NULL) != 0) {
  +        ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
  +                "shmctl: IPC_RMID: could not remove shared memory segment #%d",
  +                shmid);
  +    }
  +    if (ap_scoreboard_image == BADSHMAT)        /* now bailout */
  +        exit(APEXIT_INIT);
  +
  +#ifdef MOVEBREAK
  +    if (obrk == (char *) -1)
  +        return;                 /* nothing else to do */
  +    if (sbrk(-(MOVEBREAK)) == (char *) -1) {
  +        ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  +            "sbrk() could not move break back");
  +    }
  +#endif
  +    /*    ap_scoreboard_image->global.running_generation = 0;*/
  +}
  +
  +static void reopen_scoreboard(pool *p)
  +{
  +}
  +#endif
  +
   API_EXPORT(void) ap_add_version_component(const char *component)
   {
       if (! version_locked) {
  @@ -351,13 +451,13 @@
       }
   }
   
  -/* a clean exit from a child with proper cleanup */
  -static void clean_child_exit(int code) __attribute__ ((noreturn));
  +/* a clean exit from a child with proper cleanup 
  +   static void clean_child_exit(int code) __attribute__ ((noreturn)); */
   static void clean_child_exit(int code)
   {
  -    if (tls()->pchild) {
  -	ap_child_exit_modules(tls()->pchild, server_conf);
  -	ap_destroy_pool(tls()->pchild);
  +    if (pchild) {
  +	ap_child_exit_modules(pchild, server_conf);
  +	ap_destroy_pool(pchild);
       }
       /*    longjump(tls()->thread_exit, 1); */
   }
  @@ -1148,8 +1248,6 @@
   	    break;
   	lr = lr->next;
       }
  -    /* turn the list into a ring */
  -    lr->next = ap_listeners;
       close_unused_listeners();
   
       listenfds = ap_palloc(p, sizeof(struct pollfd));
  @@ -1332,66 +1430,10 @@
       /* ZZZ doesn't really make sense in a threaded server. */
   }
   
  -static int accept_loop(struct sockaddr *sa_client) /* ZZZZ */
  -{
  -    int srv;
  -    listen_rec *lr;
  -    int sd; /* filedesc */
  -    int csd = 0; /* filedesc */
  -    ulong len = sizeof(struct sockaddr);
  -
  -    pthread_mutex_lock(&accept_loop_lock);
  -    for(;;) {
  -        if (num_listenfds > 1) {
  -         /* more than one socket */
  -
  -          srv = poll(listenfds, num_listenfds, -1); /* INF_TIMEOUT */
  -	  if (srv < 0) {
  -	      pthread_mutex_unlock(&accept_loop_lock);
  -	      ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
  -	      clean_child_exit(1);
  -	  }
  -	  
  -	  if (srv == 0)
  -	      continue;
  -	  
  -	  /* find a listner */
  -            lr = head_listener;
  -            do {
  -                /* XXX: should we check for poll error? */
  -	      if (listenfds[lr->index].revents & POLLIN) { /* ready to read?*/
  -                    /* advance to the next listner for next loop */
  -                    head_listener = lr->next;
  -                    goto got_ir;
  -                }
  -                lr = lr->next;
  -            } while (lr != head_listener);
  -            /* if we don;t find anything then just start again */
  -            continue;
  -
  -got_ir:
  -            sd = lr->fd;
  -            }
  -        else {
  -            /* only one socket, just pretent we did the other stuff */
  -            sd = ap_listeners->fd;
  -        }
  -      
  -        csd = accept(sd, sa_client, &len);
  -
  -        if (csd >= 0)
  -            break; /* We have a socket ready for reading */
  -
  -        /* XXX: deal with error conditions... */
  -    }
  -    pthread_mutex_unlock(&accept_loop_lock);
  -    return csd;
  -}
  -
   static void process_socket(pool *ptrans, struct sockaddr *sa_client, int csd, int my_child_num) /* ZZZZ */
   {
  -  struct sockaddr sa_server; /* ZZZZ */
  -    ulong len = sizeof(struct sockaddr);
  +    struct sockaddr sa_server; /* ZZZZ */
  +    size_t len = sizeof(struct sockaddr);
       BUFF *conn_io;
       request_rec *r;
       conn_rec *current_conn;
  @@ -1469,82 +1511,153 @@
   #endif
   }
   
  -static void child_main(int child_num_arg, tls_main_t *t)
  +void * accept_thread(void * sd)
   {
  +    int csd = 0;
  +    int * temp = sd;
       struct sockaddr sa_client;
  -    pool *ptrans;
  -    int csd;
  +    size_t len = sizeof(struct sockaddr);
   
  -    /* All of initialization is a critical section, we don't care if we're
  -     * told to HUP or USR1 before we're done initializing.  For example,
  -     * we could be half way through child_init_modules() when a restart
  -     * signal arrives, and we'd have no real way to recover gracefully
  -     * and exit properly.
  -     *
  -     * I suppose a module could take forever to initialize, but that would
  -     * be either a broken module, or a broken configuration (i.e. network
  -     * problems, file locking problems, whatever). -djg
  -     */
  +    for (;;) {
  +        csd = accept(*temp, &sa_client, &len);
  +	if (csd >= 0) {
  +	    if (queue_push(&csd_queue, csd, &sa_client) != 0) {
  +	      /*	        ap_log_error*/
  +	    } 
  +	 } else{
  +	  /*	    ap_log_error()*/
  +	  }
  +    /* thread_exit */
  +    }
  +}
   
  -    csd = -1;
  -    t->my_child_num = child_num_arg;
  -    t->requests_this_child = 0;
  +void * worker_thread(void * dummy)
  +{
  +    int my_pid = *(int *)dummy;
  +    struct sockaddr sa_client;
   
  -    /* Get a sub pool for global allocations in this child, so that
  -     * we can have cleanups occur when the child exits.
  -     */
  -    ptrans = t->pchild =  ap_make_sub_pool(pconf);
  +    for (;;) {
  +        int csd = queue_pop(&csd_queue, &sa_client);
  +	pthread_t tid = pthread_self();
  +	process_socket(pchild, &sa_client, csd, my_pid);
  +    }
  +}
  +    
  +static void set_group_privs(void)
  +{
  +#ifndef WIN32
  +    if (!geteuid()) {
  +	char *name;
   
  -    fprintf(stderr, "%d child_main: status ready\n", child_num_arg);
  +	/* Get username if passed as a uid */
   
  -    (void) ap_update_child_status(child_num_arg, SERVER_READY, (request_rec*) NULL);
  +	if (ap_user_name[0] == '#') {
  +	    struct passwd *ent;
  +	    uid_t uid = atoi(&ap_user_name[1]);
  +
  +	    if ((ent = getpwuid(uid)) == NULL) {
  +		ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  +			 "getpwuid: couldn't determine user name from uid %u, "
  +			 "you probably need to modify the User directive",
  +			 (unsigned)uid);
  +		clean_child_exit(APEXIT_CHILDFATAL);
  +	    }
   
  -    while (1) {
  +	    name = ent->pw_name;
  +	}
  +	else
  +	    name = ap_user_name;
   
  -	ap_clear_pool(ptrans);
  +#ifndef OS2
  +	/* OS/2 dosen't support groups. */
   
  -	(void) ap_update_child_status(child_num_arg, SERVER_READY, (request_rec *) NULL);
  -	csd = accept_loop(&sa_client);
  -	fprintf(stderr, "%d child main: got accept\n", child_num_arg);
  -	process_socket(ptrans, &sa_client, csd, child_num_arg);
  -	
  +	/* Reset `groups' attributes. */
  +
  +	if (initgroups(name, ap_group_id) == -1) {
  +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  +			"initgroups: unable to set groups for User %s "
  +			"and Group %u", name, (unsigned)ap_group_id);
  +	    clean_child_exit(APEXIT_CHILDFATAL);
  +	}
  +#ifdef MULTIPLE_GROUPS
  +	if (getgroups(NGROUPS_MAX, group_id_list) == -1) {
  +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  +			"getgroups: unable to get group list");
  +	    clean_child_exit(APEXIT_CHILDFATAL);
  +	}
  +#endif
  +	if (setgid(ap_group_id) == -1) {
  +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  +			"setgid: unable to set group id to Group %u",
  +			(unsigned)ap_group_id);
  +	    clean_child_exit(APEXIT_CHILDFATAL);
  +	}
  +#endif
       }
  +#endif /* ndef WIN32 */
   }
   
  -static tls_main_t *create_tls(void)
  +static void child_main(int child_num_arg)
   {
  -    tls_main_t *t;
  -    int rc;
  -    t = malloc(sizeof(*t));
  -    memset(t, 0, sizeof(*t));
  -    if (ap_scoreboard_image) {
  -        t->generation = ap_scoreboard_image->global.exit_generation;
  -    }
  -    
  -    rc = pthread_setspecific(tls_main_key, t);
  -    
  -    if (rc) {
  -        fprintf(stderr, "pthread_setspecific  error\n");
  -	exit(1);
  +    listen_rec *lr;
  +    int i;
  +    pthread_t thread;
  +    int my_child_num = child_num_arg;
  +
  +
  +    my_pid = getpid();
  +    requests_this_child = 0;
  +
  +    pchild = ap_make_sub_pool(pconf);
  +
  +    /*stuff to do before we switch id's, so we have permissions.*/
  +    reopen_scoreboard(pchild);
  +    /*    SAFE_ACCEPT(accept_mutex_child_init(pchild));*/
  +
  +    set_group_privs();
  +
  +    if (!geteuid() && (setuid(ap_user_id) == -1)) {
  +        ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  +		     "setuid: unable to change uid");
  +	clean_child_exit(APEXIT_CHILDFATAL);
       }
  -    
  -    return t;
  -}
   
  -static void *child_starter(void *dummy)
  -{
  -    tls_main_t *t;
  -    
  -    t = create_tls();
  -    if (!setjmp(t->thread_exit)) {
  -        child_main((int)dummy, t);
  +    ap_child_init_modules(pchild, server_conf);
  +
  +    /*done with init critical section */
  +
  +    queue_init(&csd_queue, 2);
  +
  +    /* Setup worker threads */
  +   
  +    for (i=0; i < ap_threads_per_child; i++) {
  +      if (pthread_create(&thread, NULL, worker_thread, &my_child_num)) {
  +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  +			 "pthread_create: unable to create worker thread");
  +	    exit(1);
  +	} else {
  +	  /*	UPDATE_SCOREBOARD with thread id and state */
  +	}
  +    }    
  +    /* Setup acceptor threads */
  +
  +    lr = ap_listeners;
  +    while (lr != NULL) {
  +        if (pthread_create(&thread, NULL, accept_thread, &(lr->fd))) {
  +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  +			 "pthread_create: unable to create acceptor thread");
  +	    exit(1);
  +	} else {
  +	  /*	UPDATE_SCOREBOARD with thread id and state */
  +	}
  +	lr = lr->next;
       }
   }
   
   static int make_child(server_rec *s, int slot, time_t now) /* ZZZ */
   {
       pthread_t tid;   /* ZZZZ */
  -
  +    int pid;
       int rc;
   
       if (slot + 1 > max_daemons_limit) {
  @@ -1552,19 +1665,15 @@
       }
   
       if (one_process) {
  -	child_main(slot, tls());
  +        set_signals();
  +	child_main(slot);
       }
   
  +    Explain1("Starting new child in slot %d",slot);
       (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
  -
  -    /*tid = CreateThread(threadtype, child_starter, (void *)slot, */
  -    /*                 priority, ????);*/
   
  -    rc = pthread_create(&tid, NULL, child_starter, (void*) slot);
  -
  -    if (rc) {
  -        printf("pthread_create failed - %d\n", rc);
  -        ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, s, "pthread_create() failed");
  +    if ((pid = fork()) == -1) {
  +        ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");
           
   	/* fork didn't succeed. Fix the scoreboard or else
   	 * it will say SERVER_STARTING forever and ever
  @@ -1579,11 +1688,30 @@
   	return -1;
       }
   
  -    ap_scoreboard_image->parent[slot].tid = tid;
  +    if (!pid) {
  +#ifdef AIX_BIND_PROCESSOR
  +      /* By default, AIX binds to a single processor.  This bit unbinds
  +	 children which will then bind to another CPU.
  +      */
  +#include <sys/processor.h>
  +        int status = bindprocessor(BINDPROCESS, (int)getpid(),
  +			       PROCESSOR_CLASS_ANY);
  +	if (status != OK)
  +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
  +			 "processor unbind failed %d", status);
  +#endif
  +
  +        RAISE_SIGSTOP(MAKE_CHILD);
  +        MONCONTROL(1);
  +	set_signals();
  +    
  +	child_main(slot);
   
  -    return 0;
  -}
  +	ap_scoreboard_image->parent[slot].pid = pid;
   
  +	return 0;
  +    }
  +}
   
   /* start up a bunch of children */
   static void startup_children(int number_to_start)
  @@ -1742,7 +1870,7 @@
           pid = -1;
           
           if (pid >= 0) {
  -            child_slot = find_child_by_tid(NULL);
  +            child_slot = find_child_by_tid(0);
               if (child_slot >= 0) {
    		(void) ap_update_child_status(child_slot, SERVER_DEAD,
   					    (request_rec *) NULL);
  @@ -1818,11 +1946,9 @@
   	reinit_scoreboard(pconf);
       }
   
  -    set_signals();
   
  -    /* set up accept_loop */
  +    /* set up get_socket */
       head_listener = ap_listeners;
  -    pthread_mutex_init(&accept_loop_lock, NULL);
   
       if (ap_daemons_max_free < ap_daemons_min_free + 1)	/* Don't thrash... */
   	ap_daemons_max_free = ap_daemons_min_free + 1;
  @@ -1906,8 +2032,6 @@
   		    "SIGHUP received.  Attempting to restart");
       }
   
  -    pthread_mutex_destroy(&accept_loop_lock);
  -
   }
   
   static void standalone_main(int argc, char **argv)
  @@ -1941,15 +2065,6 @@
       int c;
       int rc; /* ZZZZ */
       int configtestonly;
  -
  -    /* Create thread local storage key */
  -    rc = pthread_key_create(&tls_main_key, NULL);
  -    if (rc) {
  -        perror("pthread_key_create failed\n");
  -        exit(1);
  -    }
  -
  -    create_tls();
   
       MONCONTROL(0); /* WTF is this? */
   
  
  
  
  1.1                  apache-apr/pthreads/src/main/fdqueue.c
  
  Index: fdqueue.c
  ===================================================================
  #include "fdqueue.h"
  
  /* XXX - We should get rid of the malloc and free used here. This should be
   * ap_palloc, I guess (mvsk) */
  
  /* Assumption: queue itself is allocated by the user */
  /* Assumption: increment and decrement are atomic on int */
  
  int queue_init(FDQueue *queue, size_t bounds) {
      pthread_mutex_init(&queue->one_big_mutex, NULL);
      pthread_cond_init(&queue->not_empty, NULL);
      pthread_cond_init(&queue->not_full, NULL);
      queue->head = queue->tail = 0;
      queue->data = malloc(bounds * sizeof(FDQueueElement));
      queue->bounds = bounds;
      return FD_QUEUE_SUCCESS;
  }
  
  void queue_destroy(FDQueue *queue) {
      free(queue->data);
      /* Ignore errors here, we can't do anything about them anyway */
      pthread_cond_destroy(&queue->not_empty);
      pthread_cond_destroy(&queue->not_full);
      pthread_mutex_destroy(&queue->one_big_mutex);
  }
  
  int queue_push(FDQueue *queue, int fd, struct sockaddr *addr) {
      if (pthread_mutex_lock(&queue->one_big_mutex) != 0) {
          return FD_QUEUE_FAILURE;
      }
      while (queue->head == ((queue->tail + 1) % queue->bounds)) {
          pthread_cond_wait(&queue->not_full, &queue->one_big_mutex);
      }
      queue->data[queue->tail].fd = fd;
      queue->data[queue->tail].addr = *addr;
      queue->tail = (queue->tail + 1) % queue->bounds;
      if (pthread_mutex_unlock(&queue->one_big_mutex) != 0) {
          return FD_QUEUE_FAILURE;
      }
      if (pthread_cond_signal(&queue->not_empty) != 0)
          perror("signal didn't work :(");
      return FD_QUEUE_SUCCESS;
  }
  
  int queue_pop(FDQueue *queue, struct sockaddr *addr) {
      int fd;
      if (pthread_mutex_lock(&queue->one_big_mutex) != 0) {
          return FD_QUEUE_FAILURE;
      }
      while (queue->head == queue->tail) {
          pthread_cond_wait(&queue->not_empty, &queue->one_big_mutex);
      }
      fd = queue->data[queue->head].fd;
      *addr = queue->data[queue->head].addr;
      queue->head = (queue->head + 1) % queue->bounds;
      if (pthread_mutex_unlock(&queue->one_big_mutex) != 0) {
          return FD_QUEUE_FAILURE;
      }
      pthread_cond_signal(&queue->not_full);
      return fd;
  }
  
  int queue_size(FDQueue *queue) {
      return ((queue->tail - queue->head + queue->bounds) % queue->bounds);
  }
  
  
  
  1.3       +2 -1      apache-apr/pthreads/src/modules/standard/mod_autoindex.c
  
  Index: mod_autoindex.c
  ===================================================================
  RCS file: /home/cvs/apache-apr/pthreads/src/modules/standard/mod_autoindex.c,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- mod_autoindex.c	1999/01/22 17:10:28	1.2
  +++ mod_autoindex.c	1999/02/03 17:50:12	1.3
  @@ -884,7 +884,8 @@
       p->ascending = (ap_toupper(direction) == D_ASCENDING);
   
       if (autoindex_opts & FANCY_INDEXING) {
  -	request_rec *rr = ap_sub_req_lookup_file(name, r);
  +        request_rec *rr = ap_sub_req_lookup_file(name, r);
  +	fprintf(stderr, "sub_req:::: %s\n", name);
   
   	if (rr->finfo.st_mode != 0) {
   	    p->lm = rr->finfo.st_mtime;
  
  
  
  1.3       +2 -2      apache-apr/pthreads/src/os/unix/multithread.c
  
  Index: multithread.c
  ===================================================================
  RCS file: /home/cvs/apache-apr/pthreads/src/os/unix/multithread.c,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- multithread.c	1999/01/27 16:15:49	1.2
  +++ multithread.c	1999/02/03 17:50:14	1.3
  @@ -37,8 +37,8 @@
       if ((pid = fork()) == -1) {
           return pid;
       } else if (pid == 0) {
  -        execvp(file, argv);
  -        return -1;
  +        if (execvp(file, argv) == -1)
  +	    return -1;
       } else 
           return pid;
   }