httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dgau...@hyperreal.org
Subject cvs commit: apache-1.3/src/modules/standard mod_status.c
Date Fri, 04 Dec 1998 19:12:18 GMT
dgaudet     98/12/04 11:12:18

  Modified:    src/include ap_mmn.h scoreboard.h
               src/main http_main.c
               src/modules/standard mod_status.c
  Log:
  - Jim's fix to the vhostrec problem wasn't sufficient for all cases...
  implement the full generation-based solution I proposed.
  - Deal with generation rollover a little more robustly.  Still not perfect.
  
  Revision  Changes    Path
  1.12      +5 -2      apache-1.3/src/include/ap_mmn.h
  
  Index: ap_mmn.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/include/ap_mmn.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- ap_mmn.h	1998/11/20 21:17:25	1.11
  +++ ap_mmn.h	1998/12/04 19:12:15	1.12
  @@ -184,11 +184,14 @@
    * 19981108 (1.3.4-dev) - added ap_method_number_of()
    *                      - changed value of M_INVALID and added WebDAV methods
    * 19981108.1           - ap_exists_config_define() is now public (minor bump)
  - *
  + * 19981204             - scoreboard changes -- added generation, changed
  + *                        exit_generation to running_generation.  Somewhere
  + *                        earlier vhostrec was added, but it's only safe to use
  + *                        as of this rev.  See scoreboard.h for documentation.
    */
   
   #ifndef MODULE_MAGIC_NUMBER_MAJOR
  -#define MODULE_MAGIC_NUMBER_MAJOR 19981108
  +#define MODULE_MAGIC_NUMBER_MAJOR 19981204
   #endif
   #define MODULE_MAGIC_NUMBER_MINOR 1                     /* 0...n */
   #define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR	/* backward compat */
  
  
  
  1.44      +29 -2     apache-1.3/src/include/scoreboard.h
  
  Index: scoreboard.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/include/scoreboard.h,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- scoreboard.h	1998/11/06 22:42:41	1.43
  +++ scoreboard.h	1998/12/04 19:12:15	1.44
  @@ -106,6 +106,29 @@
    */
   typedef unsigned vtime_t;
   
  +/* Type used for generation indicies.  Startup and every restart cause a
  + * new generation of children to be spawned.  Children within the same
  + * generation share the same configuration information -- pointers to stuff
  + * created at config time in the parent are valid across children.  For
  + * example, the vhostrec pointer in the scoreboard below is valid in all
  + * children of the same generation.
  + *
  + * The safe way to access the vhost pointer is like this:
  + *
  + * short_score *ss = pointer to whichver slot is interesting;
  + * parent_score *ps = pointer to whichver slot is interesting;
  + * server_rec *vh = ss->vhostrec;
  + *
  + * if (ps->generation != ap_my_generation) {
  + *     vh = NULL;
  + * }
  + *
  + * then if vh is not NULL it's valid in this child.
  + *
  + * This avoids various race conditions around restarts.
  + */
  +typedef int ap_generation_t;
  +
   /* stuff which the children generally write, and the parent mainly reads */
   typedef struct {
   #ifdef OPTIMIZE_TIMEOUTS
  @@ -135,11 +158,12 @@
       char client[32];		/* Keep 'em small... */
       char request[64];		/* We just want an idea... */
       server_rec *vhostrec;	/* What virtual host is being accessed? */
  +                                /* SEE ABOVE FOR SAFE USAGE! */
   } short_score;
   
   typedef struct {
  -    int exit_generation;	/* Set by the main process if a graceful
  -				   restart is required */
  +    ap_generation_t running_generation;	/* the generation of children which
  +                                         * should still be serving requests. */
   } global_score;
   
   /* stuff which the parent generally writes and the children rarely read */
  @@ -149,6 +173,7 @@
       time_t last_rtime;		/* time(0) of the last change */
       vtime_t last_vtime;		/* the last vtime the parent has seen */
   #endif
  +    ap_generation_t generation;	/* generation of this child */
   } parent_score;
   
   typedef struct {
  @@ -163,6 +188,8 @@
   API_EXPORT(int) ap_exists_scoreboard_image(void);
   
   API_VAR_EXPORT extern scoreboard *ap_scoreboard_image;
  +
  +API_VAR_EXPORT extern ap_generation_t ap_my_generation;
   
   /* for time_process_request() in http_main.c */
   #define START_PREQUEST 1
  
  
  
  1.408     +56 -60    apache-1.3/src/main/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/main/http_main.c,v
  retrieving revision 1.407
  retrieving revision 1.408
  diff -u -r1.407 -r1.408
  --- http_main.c	1998/12/03 01:07:54	1.407
  +++ http_main.c	1998/12/04 19:12:16	1.408
  @@ -1531,12 +1531,6 @@
    * We begin with routines which deal with the file itself... 
    */
   
  -/* volatile just in case */
  -static int volatile shutdown_pending;
  -static int volatile restart_pending;
  -static int volatile is_graceful;
  -static int volatile generation;
  -
   #ifdef MULTITHREAD
   /*
    * In the multithreaded mode, have multiple threads - not multiple
  @@ -1548,14 +1542,8 @@
   static void reinit_scoreboard(pool *p)
   {
       ap_assert(!ap_scoreboard_image);
  -    if (is_graceful) {
  -        int i;
  -        for (i = 0; i < HARD_SERVER_LIMIT; i++)
  -            ap_scoreboard_image->servers[i].vhostrec = NULL;
  -    } else {
  -        ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
  -        memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
  -    }
  +    ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
  +    memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
   }
   
   void cleanup_scoreboard(void)
  @@ -1636,7 +1624,7 @@
   		ap_server_argv0);
       }
       ap_scoreboard_image = (scoreboard *) m;
  -    ap_scoreboard_image->global.exit_generation = 0;
  +    ap_scoreboard_image->global.running_generation = 0;
   }
   
   static void reopen_scoreboard(pool *p)
  @@ -1723,7 +1711,7 @@
       close(fd);
       ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
       ap_scoreboard_image = (scoreboard *) m;
  -    ap_scoreboard_image->global.exit_generation = 0;
  +    ap_scoreboard_image->global.running_generation = 0;
   }
   
   static void reopen_scoreboard(pool *p)
  @@ -1803,7 +1791,7 @@
       close(fd);
   #endif
       ap_scoreboard_image = (scoreboard *) m;
  -    ap_scoreboard_image->global.exit_generation = 0;
  +    ap_scoreboard_image->global.running_generation = 0;
   }
   
   static void reopen_scoreboard(pool *p)
  @@ -1895,7 +1883,7 @@
   	    "sbrk() could not move break back");
       }
   #endif
  -    ap_scoreboard_image->global.exit_generation = 0;
  +    ap_scoreboard_image->global.running_generation = 0;
   }
   
   static void reopen_scoreboard(pool *p)
  @@ -1962,41 +1950,32 @@
   /* Called by parent process */
   static void reinit_scoreboard(pool *p)
   {
  -    if (is_graceful && ap_scoreboard_image) {
  -        int i;
  -        for (i = 0; i < HARD_SERVER_LIMIT; i++)
  -            ap_scoreboard_image->servers[i].vhostrec = NULL;
  -#ifdef SCOREBOARD_FILE
  -            force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
  -#endif
  -    } else {
  -        int exit_gen = 0;
  -        if (ap_scoreboard_image)
  -            exit_gen = ap_scoreboard_image->global.exit_generation;
  +    int running_gen = 0;
  +    if (ap_scoreboard_image)
  +	running_gen = ap_scoreboard_image->global.running_generation;
   
   #ifndef SCOREBOARD_FILE
  -        if (ap_scoreboard_image == NULL) {
  -            setup_shared_mem(p);
  -        }
  -        memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
  -        ap_scoreboard_image->global.exit_generation = exit_gen;
  +    if (ap_scoreboard_image == NULL) {
  +	setup_shared_mem(p);
  +    }
  +    memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
  +    ap_scoreboard_image->global.running_generation = running_gen;
   #else
  -        ap_scoreboard_image = &_scoreboard_image;
  -        ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
  +    ap_scoreboard_image = &_scoreboard_image;
  +    ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
   
  -        scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR,
0644);
  -        if (scoreboard_fd == -1) {
  -            perror(ap_scoreboard_fname);
  -            fprintf(stderr, "Cannot open scoreboard file:\n");
  -            exit(APEXIT_INIT);
  -        }
  -        ap_register_cleanup(p, NULL, cleanup_scoreboard_file, ap_null_cleanup);
  +    scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644);
  +    if (scoreboard_fd == -1) {
  +	perror(ap_scoreboard_fname);
  +	fprintf(stderr, "Cannot open scoreboard file:\n");
  +	exit(APEXIT_INIT);
  +    }
  +    ap_register_cleanup(p, NULL, cleanup_scoreboard_file, ap_null_cleanup);
   
  -        memset((char *) ap_scoreboard_image, 0, sizeof(*ap_scoreboard_image));
  -        ap_scoreboard_image->global.exit_generation = exit_gen;
  -        force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
  +    memset((char *) ap_scoreboard_image, 0, sizeof(*ap_scoreboard_image));
  +    ap_scoreboard_image->global.running_generation = running_gen;
  +    force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
   #endif
  -    }
   }
   
   /* Routines called to deal with the scoreboard image
  @@ -2572,6 +2551,12 @@
       deferred_die = 1;
   }
   
  +/* volatile just in case */
  +static int volatile shutdown_pending;
  +static int volatile restart_pending;
  +static int volatile is_graceful;
  +int volatile ap_my_generation;
  +
   #ifdef WIN32
   /*
    * Signalling Apache on NT.
  @@ -3618,7 +3603,7 @@
   	ap_clear_pool(ptrans);
   
   	ap_sync_scoreboard_image();
  -	if (ap_scoreboard_image->global.exit_generation >= generation) {
  +	if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
   	    clean_child_exit(0);
   	}
   
  @@ -3759,7 +3744,7 @@
   	     * without reliable signals
   	     */
   	    ap_sync_scoreboard_image();
  -	    if (ap_scoreboard_image->global.exit_generation >= generation) {
  +	    if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
   		clean_child_exit(0);
   	    }
   	}
  @@ -3864,7 +3849,7 @@
   				       (request_rec *) NULL);
   
   	    ap_sync_scoreboard_image();
  -	    if (ap_scoreboard_image->global.exit_generation >= generation) {
  +	    if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
   		ap_bclose(conn_io);
   		clean_child_exit(0);
   	    }
  @@ -3932,6 +3917,16 @@
       Explain1("Starting new child in slot %d", slot);
       (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
   
  +    /* clean up the slot's vhostrec pointer now that it is being re-used,
  +     * and mark the slot as beloging to a new generation.
  +     */
  +    /* XXX: there's still a race condition here for file-based scoreboards...
  +     * but... like, do we really care to spend yet another write() operation
  +     * here? -djg
  +     */
  +    ap_scoreboard_image->servers[slot].vhostrec = NULL;
  +    ap_scoreboard_image->parent[slot].generation = ap_my_generation;
  +
   #ifndef _OSD_POSIX
       if ((pid = fork()) == -1) {
   #else /*_OSD_POSIX*/
  @@ -4229,7 +4224,6 @@
       ap_standalone = 1;
   
       is_graceful = 0;
  -    ++generation;
   
       if (!one_process) {
   	detach();
  @@ -4262,7 +4256,9 @@
   	ap_init_modules(pconf, server_conf);
   	version_locked++;	/* no more changes to server_version */
   	SAFE_ACCEPT(accept_mutex_init(pconf));
  -	reinit_scoreboard(pconf);
  +	if (!is_graceful) {
  +	    reinit_scoreboard(pconf);
  +	}
   #ifdef SCOREBOARD_FILE
   	else {
   	    ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
  @@ -4406,14 +4402,16 @@
   	    clean_parent_exit(0);
   	}
   
  +	/* advance to the next generation */
  +	/* XXX: we really need to make sure this new generation number isn't in
  +	 * use by any of the children.
  +	 */
  +	++ap_my_generation;
   	if (is_graceful) {
   #ifndef SCOREBOARD_FILE
   	    int i;
   #endif
  -
  -	    /* USE WITH CAUTION:  Graceful restarts are not known to work
  -	     * in various configurations on the architectures we support. */
  -	    ap_scoreboard_image->global.exit_generation = generation;
  +	    ap_scoreboard_image->global.running_generation = ap_my_generation;
   	    update_scoreboard_global();
   
   	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
  @@ -4446,7 +4444,6 @@
   	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
   			"SIGHUP received.  Attempting to restart");
   	}
  -	++generation;
       } while (restart_pending);
   
       /*add_common_vars(NULL);*/
  @@ -5168,7 +5165,7 @@
   
       my_pid = getpid();
   
  -    ++generation;
  +    ++ap_my_generation;
   
       copy_listeners(pconf);
       ap_restart_time = time(NULL);
  @@ -5548,7 +5545,6 @@
       processes_to_create = nchild;
   
       is_graceful = 0;
  -    ++generation;
   
       ap_snprintf(signal_prefix_string, sizeof(signal_prefix_string),
   	        "ap%d", getpid());
  @@ -5709,7 +5705,7 @@
    			"SetEvent for child process in slot #%d", i);
   	    }
   	}
  -	++generation;
  +	++ap_my_generation;
       } while (restart_pending);
   
       /* If we dropped out of the loop we definitly want to die completely. We need to
  
  
  
  1.103     +6 -6      apache-1.3/src/modules/standard/mod_status.c
  
  Index: mod_status.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_status.c,v
  retrieving revision 1.102
  retrieving revision 1.103
  diff -u -r1.102 -r1.103
  --- mod_status.c	1998/12/03 14:38:05	1.102
  +++ mod_status.c	1998/12/04 19:12:18	1.103
  @@ -254,7 +254,7 @@
       char stat_buffer[HARD_SERVER_LIMIT];
       int pid_buffer[HARD_SERVER_LIMIT];
       clock_t tu, ts, tcu, tcs;
  -    char *vhost;
  +    server_rec *vhost;
   
       tu = ts = tcu = tcs = 0;
   
  @@ -309,10 +309,6 @@
       for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
   	score_record = ap_scoreboard_image->servers[i];
   	ps_record = ap_scoreboard_image->parent[i];
  -	if (score_record.vhostrec)
  -	    vhost = score_record.vhostrec->server_hostname;
  -	else
  -	    vhost = "NULL";
   	res = score_record.status;
   	stat_buffer[i] = status_flags[res];
   	pid_buffer[i] = (int) ps_record.pid;
  @@ -492,6 +488,10 @@
   	for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
   	    score_record = ap_scoreboard_image->servers[i];
   	    ps_record = ap_scoreboard_image->parent[i];
  +	    vhost = score_record.vhostrec;
  +	    if (ps_record.generation != ap_my_generation) {
  +		vhost = NULL;
  +	    }
   
   #if defined(NO_GETTIMEOFDAY)
   #ifndef NO_TIMES
  @@ -658,7 +658,7 @@
   			    ap_rprintf(r,
   			     "<td>%s<td nowrap>%s<td nowrap>%s</tr>\n\n",
   			     score_record.client,
  -			     (score_record.vhostrec ? vhost : "NULL"),
  +			     vhost ? vhost->server_hostname : "(unavailable)",
   			     ap_escape_html(r->pool, score_record.request));
   		    }		/* no_table_report */
   		}			/* !short_report */
  
  
  

Mime
View raw message