You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ma...@hyperreal.org on 1999/05/24 04:10:28 UTC

cvs commit: apache-apr/pthreads/src/main http_accept.c http_main.c

manoj       99/05/23 19:10:28

  Modified:    pthreads/src/include http_main.h
               pthreads/src/main http_accept.c http_main.c
  Log:
  Switch to using a pipe to notify children of graceful shutodwn instead
  of a signal. This also naturally solves a problem with graceful shutdown
  of children blocked on the accept mutex.
  
  Revision  Changes    Path
  1.6       +3 -0      apache-apr/pthreads/src/include/http_main.h
  
  Index: http_main.h
  ===================================================================
  RCS file: /home/cvs/apache-apr/pthreads/src/include/http_main.h,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -u -r1.5 -r1.6
  --- http_main.h	1999/04/09 04:10:35	1.5
  +++ http_main.h	1999/05/24 02:10:25	1.6
  @@ -58,6 +58,9 @@
   #ifndef APACHE_HTTP_MAIN_H
   #define APACHE_HTTP_MAIN_H
   
  +/* Pipe used to signal a graceful child shutdown */
  +extern int ap_pipe_of_death[2];
  +
   #ifdef __cplusplus
   extern "C" {
   #endif
  
  
  
  1.15      +19 -15    apache-apr/pthreads/src/main/http_accept.c
  
  Index: http_accept.c
  ===================================================================
  RCS file: /home/cvs/apache-apr/pthreads/src/main/http_accept.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -u -r1.14 -r1.15
  --- http_accept.c	1999/05/20 05:00:41	1.14
  +++ http_accept.c	1999/05/24 02:10:26	1.15
  @@ -331,7 +331,6 @@
    */
   static listen_rec *head_listener;
   static struct pollfd *listenfds;
  -static int pipe_of_death;
   
   void accept_parent_init(pool *pconf, int listener_count)
   {
  @@ -344,7 +343,6 @@
                    int worker_threads_per_child)
   {
       int i;
  -    int pipe_pair_of_death[2];
       listen_rec *lr;
   
       SAFE_ACCEPT(intra_mutex_init(pchild, 1));
  @@ -353,15 +351,7 @@
       head_listener = ap_listeners;
   
       listenfds = ap_palloc(pchild, sizeof(struct pollfd) * (num_listenfds + 1));
  -
  -    if (pipe(pipe_pair_of_death) == -1) {
  -        ap_log_error(APLOG_MARK, APLOG_ERR,
  -	             (const server_rec*) ap_get_server_conf(),
  -		     "pipe: (pipe_of_death)");
  -	clean_child_exit(1);
  -    }
  -    pipe_of_death = pipe_pair_of_death[1];
  -    listenfds[0].fd = pipe_pair_of_death[0];
  +    listenfds[0].fd = ap_pipe_of_death[0];
       listenfds[0].events = POLLIN;
       listenfds[0].revents = 0;
       for (lr = ap_listeners, i = 1; i <= num_listenfds; lr = lr->next, ++i) {
  @@ -380,7 +370,9 @@
       int csd = -1;
       int sd;
       int srv;
  +    int ret;
       listen_rec *lr;
  +    char pipe_read_char;
   
       size_t len = sizeof(struct sockaddr);
   
  @@ -400,6 +392,21 @@
                   break;
   
               srv = poll(listenfds, num_listenfds + 1, -1);
  +            if (listenfds[0].revents & POLLIN) {
  +                /* A process has gotten a signal on the shutdown pipe.
  +                 * Check if we're the lucky process to die. */
  +                ret = read(listenfds[0].fd, &pipe_read_char, 1);
  +                if (ret == -1 && errno == EAGAIN) {
  +                    /* It lost the lottery. It must continue to suffer through
  +                     * a life of servitude */
  +                    continue;
  +                }
  +                else {
  +                    /* It won the lottery (or something else is very wrong).
  +                     * Embrace death with open arms. */
  +                    break;
  +                }
  +            }
               if (workers_may_exit)
                   break;
               if (srv < 0) {
  @@ -472,6 +479,7 @@
               break;
           }
       }
  +    workers_may_exit = 1;
       return -1;
   }
   
  @@ -479,15 +487,11 @@
   {
       int i;
       int index = find_child_by_pid(getpid());
  -    char char_of_death = '!';
   
       parent_score *ss = &ap_scoreboard_image->parent[index];
   
       requests_this_child = 0;
       workers_may_exit = 1;
  -
  -    /* Kick threads out of poll */    
  -    (void) write(pipe_of_death, &char_of_death, 1);
   
       for (i = 0; i < ss->worker_threads; i++) {
   	pthread_join(ap_scoreboard_image->servers[index][i].tid, NULL);
  
  
  
  1.81      +26 -9     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.80
  retrieving revision 1.81
  diff -u -u -r1.80 -r1.81
  --- http_main.c	1999/05/20 04:33:32	1.80
  +++ http_main.c	1999/05/24 02:10:27	1.81
  @@ -216,6 +216,7 @@
   array_header *ap_server_config_defines;
   pool *pchild;		/* Pool for httpd child stuff */
   
  +int ap_pipe_of_death[2];
   
   /* thread local storage code that isn't used right now */
   
  @@ -1963,7 +1964,6 @@
       /* XXX - Do the appropriate thing for each signal */
       switch (signal_received) {
           case SIGWINCH:
  -       	    graceful_sig_handler(SIGWINCH);
     	    for (j = 0; j < ap_threads_per_child + ap_acceptors_per_child; 
   		 j++) { 
                   /* Useful for debugging */
  @@ -2158,11 +2158,11 @@
       }
       max_daemons_limit = last_non_dead + 1;
       if (idle_count > ap_daemons_max_free) {
  -        /* kill off one child... we use SIGWINCH because that'll cause it to
  -	 * shut down gracefully, in case it happened to pick up a request
  -	 * while we were counting
  -	 */
  -        kill(ap_scoreboard_image->parent[to_kill].pid, SIGWINCH);
  +        /* Kill off one child */
  +        char char_of_death = '!';
  +        if (write(ap_pipe_of_death[1], &char_of_death, 1) == -1) {
  +            ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write ap_pipe_of_death");
  +        }
           idle_spawn_rate = 1;
       }
       else if (idle_count < ap_daemons_min_free) {
  @@ -2288,6 +2288,20 @@
           ap_restart_time = time(NULL); /* ZZZZZ */
       }
       ap_clear_pool(pconf);
  +    if (pipe(ap_pipe_of_death) == -1) {
  +        ap_log_error(APLOG_MARK, APLOG_ERR,
  +                     (const server_rec*) ap_get_server_conf(),
  +                     "pipe: (pipe_of_death)");
  +        exit(1);
  +    }
  +    ap_note_cleanups_for_fd(pconf, ap_pipe_of_death[0]);
  +    ap_note_cleanups_for_fd(pconf, ap_pipe_of_death[1]);
  +    if (fcntl(ap_pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
  +        ap_log_error(APLOG_MARK, APLOG_ERR,
  +                     (const server_rec*) ap_get_server_conf(),
  +                     "fcntl: O_NONBLOCKing (pipe_of_death)");
  +        exit(1);
  +    }
       ptemp = ap_make_sub_pool(pconf);
       server_conf = ap_read_config(pconf, ptemp, ap_server_confname);
       listener_count = setup_listeners(pconf);
  @@ -2385,14 +2399,17 @@
   
       if (is_graceful) {
   	int i, j;
  +        char char_of_death = '!';
   
   	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
   		    "SIGWINCH received.  Doing graceful restart");
   
   	/* kill off the idle ones */
  -	if (ap_killpg(pgrp, SIGWINCH) < 0) {
  -	    ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGWINCH");
  -	}
  +        for (i = 0; i < ap_daemons_limit; ++i) {
  +            if (write(ap_pipe_of_death[1], &char_of_death, 1) == -1) {
  +                ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write ap_pipe_of_death");
  +            }
  +        }
   
   	/* This is mostly for debugging... so that we know what is still
   	    * gracefully dealing with existing request.