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/03 11:11:44 UTC

cvs commit: apachen/src/main http_main.c

dgaudet     97/11/03 02:11:44

  Modified:    src      CHANGES
               src/main http_main.c
  Log:
  Fix a mild race condition in unblock_alarms() involving a SIGALRM showing
  up after a SIGTERM.
  
  PR:		1211
  Reviewed by:	Marc Slemko, Martin Kraemer
  
  Revision  Changes    Path
  1.484     +3 -0      apachen/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/CHANGES,v
  retrieving revision 1.483
  retrieving revision 1.484
  diff -u -r1.483 -r1.484
  --- CHANGES	1997/11/03 04:33:16	1.483
  +++ CHANGES	1997/11/03 10:11:39	1.484
  @@ -1,5 +1,8 @@
   Changes with Apache 1.3b3
   
  +  *) A mild SIGTERM/SIGALRM race condition was eliminated.
  +     [Dean Gaudet] PR#1211
  +
     *) Warn user that default path has changed if /usr/local/etc/httpd
        is found on the system.  [Lars Eilebrecht]
   
  
  
  
  1.243     +28 -27    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.242
  retrieving revision 1.243
  diff -u -r1.242 -r1.243
  --- http_main.c	1997/11/01 22:15:59	1.242
  +++ http_main.c	1997/11/03 10:11:42	1.243
  @@ -678,6 +678,14 @@
   }
   #endif
   
  +/* a clean exit from a child with proper cleanup */
  +static void __attribute__((noreturn)) clean_child_exit(int code)
  +{
  +    child_exit_modules(pconf, server_conf);
  +    destroy_pool(pconf);
  +    exit(code);
  +}
  +
   void timeout(int sig)
   {				/* Also called on SIGPIPE */
       char errstr[MAX_STRING_LEN];
  @@ -688,6 +696,9 @@
   	alarm_pending = 1;
   	return;
       }
  +    if (exit_after_unblock) {
  +	clean_child_exit(0);
  +    }
   
       if (!current_conn) {
   	ap_longjmp(jmpbuffer, 1);
  @@ -760,10 +771,16 @@
       --alarms_blocked;
       if (alarms_blocked == 0) {
   	if (exit_after_unblock) {
  +	    /* We have a couple race conditions to deal with here, we can't
  +	     * allow a timeout that comes in this small interval to allow
  +	     * the child to jump back to the main loop.  Instead we block
  +	     * alarms again, and then note that exit_after_unblock is
  +	     * being dealt with.  We choose this way to solve this so that
  +	     * the common path through unblock_alarms() is really short.
  +	     */
  +	    ++alarms_blocked;
   	    exit_after_unblock = 0;
  -	    child_exit_modules(pconf, server_conf);
  -	    destroy_pool(pconf);
  -	    exit(0);
  +	    clean_child_exit(0);
   	}
   	if (alarm_pending) {
   	    alarm_pending = 0;
  @@ -1964,9 +1981,7 @@
   	exit_after_unblock = 1;
       }
       else {
  -	child_exit_modules(pconf, server_conf);
  -	destroy_pool(pconf);
  -	exit(0);
  +	clean_child_exit(0);
       }
   }
   
  @@ -2668,16 +2683,12 @@
   
   	sync_scoreboard_image();
   	if (scoreboard_image->global.exit_generation >= generation) {
  -	    child_exit_modules(pconf, server_conf);
  -	    destroy_pool(pconf);
  -	    exit(0);
  +	    clean_child_exit(0);
   	}
   
   	if ((max_requests_per_child > 0
   	     && ++requests_this_child >= max_requests_per_child)) {
  -	    child_exit_modules(pconf, server_conf);
  -	    destroy_pool(pconf);
  -	    exit(0);
  +	    clean_child_exit(0);
   	}
   
   	(void) update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
  @@ -2700,9 +2711,7 @@
   		    if (errno == EFAULT) {
   			aplog_error(APLOG_MARK, APLOG_ERR, server_conf,
   				    "select: (listen) fatal, child exiting");
  -			child_exit_modules(pconf, server_conf);
  -			destroy_pool(pconf);
  -			exit(1);
  +			clean_child_exit(1);
   		    }
   #endif
   		    aplog_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
  @@ -2733,9 +2742,7 @@
   		    break;
   		if (deferred_die) {
   		    /* we didn't get a socket, and we were told to die */
  -		    child_exit_modules(pconf, server_conf);
  -		    destroy_pool(pconf);
  -		    exit(0);
  +		    clean_child_exit(0);
   		}
   	    }
   
  @@ -2758,18 +2765,14 @@
   	    usr1_just_die = 1;
   	    if (deferred_die) {
   		/* ok maybe not, see ya later */
  -		child_exit_modules(pconf, server_conf);
  -		destroy_pool(pconf);
  -		exit(0);
  +		clean_child_exit(0);
   	    }
   	    /* or maybe we missed a signal, you never know on systems
   	     * without reliable signals
   	     */
   	    sync_scoreboard_image();
   	    if (scoreboard_image->global.exit_generation >= generation) {
  -		child_exit_modules(pconf, server_conf);
  -		destroy_pool(pconf);
  -		exit(0);
  +		clean_child_exit(0);
   	    }
   	}
   
  @@ -2855,9 +2858,7 @@
   	    sync_scoreboard_image();
   	    if (scoreboard_image->global.exit_generation >= generation) {
   		bclose(conn_io);
  -		child_exit_modules(pconf, server_conf);
  -		destroy_pool(pconf);
  -		exit(0);
  +		clean_child_exit(0);
   	    }
   
   	    /* In case we get a graceful restart while we're blocked