httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@apache.org
Subject cvs commit: httpd-2.0/server/mpm/prefork mpm.h prefork.c
Date Thu, 07 Jun 2001 00:09:17 GMT
rbb         01/06/06 17:09:17

  Modified:    include  httpd.h mpm_common.h
               server   mpm_common.c
               server/mpm/prefork mpm.h prefork.c
  Log:
  First pass at the pipe_of_death logic for the prefork MPM.  This does
  pass some initial testing, but it needs to be banged on more.  It looks
  like if the server gets a lot of requests to restart all at once, there
  are potential problems, but other than that this does seem to solve our
  current restart issues.
  
  Revision  Changes    Path
  1.153     +2 -0      httpd-2.0/include/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/include/httpd.h,v
  retrieving revision 1.152
  retrieving revision 1.153
  diff -u -d -b -w -u -r1.152 -r1.153
  --- httpd.h	2001/06/03 11:59:18	1.152
  +++ httpd.h	2001/06/07 00:09:14	1.153
  @@ -1542,6 +1542,8 @@
   
   #endif
   
  +#define AP_NORESTART		APR_OS_START_USEERR + 1
  +
   #ifdef __cplusplus
   }
   #endif
  
  
  
  1.21      +43 -0     httpd-2.0/include/mpm_common.h
  
  Index: mpm_common.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/include/mpm_common.h,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -d -b -w -u -r1.20 -r1.21
  --- mpm_common.h	2001/03/22 12:32:21	1.20
  +++ mpm_common.h	2001/06/07 00:09:15	1.21
  @@ -164,6 +164,49 @@
   
   #define AP_MPM_HARD_LIMITS_FILE APACHE_MPM_DIR "/mpm_default.h"
   
  +#ifdef AP_MPM_USES_POD
  +
  +typedef struct ap_pod_t ap_pod_t;
  +
  +struct ap_pod_t {
  +    apr_file_t *pod_in;
  +    apr_file_t *pod_out;
  +    apr_pool_t *p;
  +};
  +
  +/**
  + * Open the pipe-of-death.  The pipe of death is used to tell all child
  + * processes that it is time to die gracefully.
  + * @param p The pool to use for allocating the pipe
  + */
  +AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod);
  +
  +/**
  + * Check the pipe to determine if the process has been signalled to die.
  + */
  +AP_DECLARE(apr_status_t) ap_mpm_pod_check(ap_pod_t *pod);
  +
  +/**
  + * Close the pipe-of-death
  + */
  +AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t *pod);
  +
  +/**
  + * Write data to the pipe-of-death, signalling that one child process
  + * should die.
  + * @param p The pool to use when allocating any required structures.
  + */
  +AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t *pod);
  +
  +/**
  + * Write data to the pipe-of-death, signalling that all child process
  + * should die.
  + * @param p The pool to use when allocating any required structures.
  + * @param num The number of child processes to kill
  + */
  +AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t *pod, int num);
  +#endif
  +
   #ifdef __cplusplus
   }
   #endif
  
  
  
  1.48      +84 -0     httpd-2.0/server/mpm_common.c
  
  Index: mpm_common.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm_common.c,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -d -b -w -u -r1.47 -r1.48
  --- mpm_common.c	2001/05/16 20:51:28	1.47
  +++ mpm_common.c	2001/06/07 00:09:15	1.48
  @@ -78,6 +78,7 @@
   #include "mpm.h"
   #include "mpm_common.h"
   #include "ap_mpm.h"
  +#include "ap_listen.h"
   
   #ifdef HAVE_PWD_H
   #include <pwd.h>
  @@ -338,4 +339,87 @@
   }
   #endif /* def NEED_INITGROUPS */
   
  +#ifdef AP_MPM_USES_POD
  +
  +AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod)
  +{
  +    apr_status_t rv;
  +
  +    *pod = apr_palloc(p, sizeof(**pod));
  +    rv = apr_file_pipe_create(&((*pod)->pod_in), &((*pod)->pod_out), p);
  +    apr_file_pipe_timeout_set((*pod)->pod_out, 0);
  +    (*pod)->p = p;
  +    return rv;
  +}
  +
  +AP_DECLARE(apr_status_t) ap_mpm_pod_check(ap_pod_t *pod)
  +{
  +    char c;
  +    apr_size_t len = 1;
  +    apr_status_t rv;
  +
  +    rv = apr_file_read(pod->pod_in, &c, &len);
  +
  +    if ((rv == APR_SUCCESS) && (len == 1)) {
  +        return APR_SUCCESS;
  +    }
  +    if (rv != APR_SUCCESS) {
  +        return rv;
  +    }
  +    return AP_NORESTART;
  +}
  +
  +AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t *pod)
  +{
  +    apr_status_t rv;
  +
  +    rv = apr_file_close(pod->pod_out);
  +    if (rv != APR_SUCCESS) {
  +        return rv;
  +    }
  +
  +    rv = apr_file_close(pod->pod_in);
  +    if (rv != APR_SUCCESS) {
  +        return rv;
  +    }
  +    return rv;
  +}
  +
  +AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t *pod)
  +{
  +    apr_socket_t *sock;
  +    apr_sockaddr_t *sa;
  +    apr_status_t rv;
  +    char char_of_death = '!';
  +    apr_size_t one = 1;
  +
  +    do {
  +        if ((rv = apr_file_write(pod->pod_out, &char_of_death, &one))
  +                                 != APR_SUCCESS) {
  +            if (APR_STATUS_IS_EINTR(rv)) {
  +                continue;
  +            }
  +            else {
  +                ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
  +                             "write pipe_of_death");
  +                return rv;
  +            }
  +        }
  +    } while (1);
  +    
  +    apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, ap_listeners->bind_addr->port,
0, pod->p);
  +    apr_socket_create(&sock, sa->family, SOCK_STREAM, pod->p);
  +    apr_connect(sock, sa);    
  +    apr_socket_close(sock);
   
  +    return APR_SUCCESS;
  +}
  +
  +AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t *pod, int num)
  +{
  +    int i;
  +    for (i = 0; i < num; i++) {
  +        ap_mpm_pod_signal(pod);
  +    }
  +}
  +#endif
  
  
  
  1.12      +1 -0      httpd-2.0/server/mpm/prefork/mpm.h
  
  Index: mpm.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/prefork/mpm.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -d -b -w -u -r1.11 -r1.12
  --- mpm.h	2001/04/13 19:00:38	1.11
  +++ mpm.h	2001/06/07 00:09:16	1.12
  @@ -68,6 +68,7 @@
   
   #define MPM_NAME "Prefork"
   
  +#define AP_MPM_USES_POD 1
   #define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
   #define MPM_SYNC_CHILD_TABLE() (ap_sync_scoreboard_image())
   #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
  
  
  
  1.177     +31 -36    httpd-2.0/server/mpm/prefork/prefork.c
  
  Index: prefork.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/prefork/prefork.c,v
  retrieving revision 1.176
  retrieving revision 1.177
  diff -u -d -b -w -u -r1.176 -r1.177
  --- prefork.c	2001/06/04 04:00:03	1.176
  +++ prefork.c	2001/06/07 00:09:16	1.177
  @@ -140,6 +140,8 @@
   static int ap_daemons_max_free=0;
   static int ap_daemons_limit=0;
   
  +static ap_pod_t *pod;
  +
   /*
    * The max child slot ever assigned, preserved across restarts.  Necessary
    * to deal with MaxClients changes across SIGWINCH restarts.  We use this
  @@ -182,6 +184,8 @@
   char tpf_server_name[INETD_SERVNAME_LENGTH+1];
   #endif /* TPF */
   
  +int die_now = 0;
  +
   #ifdef GPROF
   /* 
    * change directory for gprof to plop the gmon.out file
  @@ -232,7 +236,7 @@
       if (pchild) {
   	apr_pool_destroy(pchild);
       }
  -    ap_scoreboard_image->parent[my_child_num].process_status = SB_WORKING;
  +    ap_mpm_pod_close(pod);
       chdir_for_gprof();
       exit(code);
   }
  @@ -378,15 +382,7 @@
   static void please_die_gracefully(int sig)
   {
       /* clean_child_exit(0); */
  -    ap_scoreboard_image->parent[my_child_num].process_status = SB_IDLE_DIE;
  -    if (sig == SIGHUP) {
  -        (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num),
  -                                      SERVER_GRACEFUL, (request_rec *) NULL);
  -    }
  -    else {
  -        (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num),
  -                                      SERVER_IDLE_KILL, (request_rec *) NULL);
  -    }
  +    die_now = 1;
   }
   
   /* volatile just in case */
  @@ -414,9 +410,11 @@
   	return;
       }
       restart_pending = 1;
  +#if 0
       if ((is_graceful = (sig == SIGWINCH))) {
           apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
       }
  +#endif
   }
   
   static void set_signals(void)
  @@ -479,12 +477,9 @@
   
       /* we want to ignore HUPs and WINCH while we're busy processing one */
       sigaddset(&sa.sa_mask, SIGHUP);
  -    sigaddset(&sa.sa_mask, SIGWINCH);
       sa.sa_handler = restart;
       if (sigaction(SIGHUP, &sa, NULL) < 0)
   	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
  -    if (sigaction(SIGWINCH, &sa, NULL) < 0)
  -	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
   #else
       if (!one_process) {
   	apr_signal(SIGSEGV, sig_coredump);
  @@ -513,7 +508,7 @@
       apr_signal(SIGHUP, restart);
   #endif /* SIGHUP */
   #ifdef SIGWINCH
  -    apr_signal(SIGWINCH, restart);
  +    apr_signal(SIGWINCH, SIG_IGN);
   #endif /* SIGWINCH */
   #ifdef SIGPIPE
       apr_signal(SIGPIPE, SIG_IGN);
  @@ -533,9 +528,6 @@
   static int requests_this_child;
   static fd_set main_fds;
   
  -#define I_AM_TO_SHUTDOWN()                                                   \
  -(ap_scoreboard_image->parent[my_child_num].process_status != SB_WORKING)
  -   
   int ap_graceful_stop_signalled(void)
   {
       /* not ever called anymore... */
  @@ -581,12 +573,11 @@
       apr_signal(SIGHUP, please_die_gracefully);
   
       ap_sync_scoreboard_image();
  -    while (!I_AM_TO_SHUTDOWN()) {
  +    while (!die_now) {
   
   	/* Prepare to receive a SIGWINCH due to graceful restart so that
   	 * we can exit cleanly.
   	 */
  -	apr_signal(SIGWINCH, please_die_gracefully);
           apr_signal(SIGTERM, just_die);
   
   	/*
  @@ -669,14 +660,21 @@
   	     */
   	    for (;;) {
                   ap_sync_scoreboard_image();
  -		if (I_AM_TO_SHUTDOWN()) {
  +		if (die_now) {
   		    /* we didn't get a socket, and we were told to die */
   		    clean_child_exit(0);
   		}
   		stat = apr_accept(&csd, sd, ptrans);
   		if (stat == APR_SUCCESS || !APR_STATUS_IS_EINTR(stat))
   		    break;
  +                /* In reality, this could be done later, but to keep it
  +                 * consistent with MPMs that have a thread race-condition,
  +                 * we will do it here.
  +                 */
  +                if (!ap_mpm_pod_check(pod)) {
  +                    die_now = 1;
   	    }
  +	    }
   
   	    if (stat == APR_SUCCESS)
   		break;		/* We have a socket ready for reading */
  @@ -777,19 +775,13 @@
   	    }
   
               ap_sync_scoreboard_image();
  -	    if (I_AM_TO_SHUTDOWN()) {
  +	    if (die_now) {
   		clean_child_exit(0);
   	    }
   	}
   
   	SAFE_ACCEPT(accept_mutex_off());	/* unlock after "accept" */
   
  -	/* We've got a socket, let's at least process one request off the
  -	 * socket before we accept a graceful restart request.  We set
  -	 * the signal to ignore because we don't want to disturb any
  -	 * third party code.
  -	 */
  -	apr_signal(SIGWINCH, SIG_IGN);
   	/*
   	 * We now have a connection, so set it up with the appropriate
   	 * socket options, file descriptors, and read/write buffers.
  @@ -894,7 +886,6 @@
   	 * requested there's no race condition here.
   	 */
   	apr_signal(SIGHUP, please_die_gracefully);
  -	apr_signal(SIGWINCH, please_die_gracefully);
   	apr_signal(SIGTERM, just_die);
           ap_scoreboard_image->parent[slot].process_status = SB_WORKING;
   	child_main(slot);
  @@ -940,7 +931,7 @@
   #endif
   static int hold_off_on_exponential_spawning;
   
  -static void perform_idle_server_maintenance(void)
  +static void perform_idle_server_maintenance(apr_pool_t *p)
   {
       int i;
       int to_kill;
  @@ -1002,7 +993,7 @@
   	 * 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);
  +	ap_mpm_pod_signal(pod);
   	idle_spawn_rate = 1;
       }
       else if (idle_count < ap_daemons_min_free) {
  @@ -1088,6 +1079,7 @@
   {
       int index;
       int remaining_children_to_start;
  +    apr_status_t rv;
   
       pconf = _pconf;
   
  @@ -1099,6 +1091,11 @@
   	/* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
   	return 1;
       }
  +    if ((rv = ap_mpm_pod_open(pconf, &pod))) {
  +        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
  +		"Could not open pipe-of-death.");
  +        return 1;
  +    }
   
       SAFE_ACCEPT(accept_mutex_init(pconf));
       if (!is_graceful) {
  @@ -1209,7 +1206,7 @@
   	    continue;
   	}
   
  -	perform_idle_server_maintenance();
  +	perform_idle_server_maintenance(pconf);
   #ifdef TPF
       shutdown_pending = os_check_server(tpf_server_name);
       ap_check_signals();
  @@ -1244,7 +1241,6 @@
   
       /* we've been told to restart */
       apr_signal(SIGHUP, SIG_IGN);
  -    apr_signal(SIGWINCH, SIG_IGN);
       if (one_process) {
   	/* not worth thinking about */
   	return 1;
  @@ -1264,12 +1260,11 @@
   
       if (is_graceful) {
   	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
  -		    "SIGWINCH received.  Doing graceful restart");
  +		    "Graceful restart requested, doing restart");
   
   	/* kill off the idle ones */
  -	if (unixd_killpg(getpgrp(), SIGWINCH) < 0) {
  -	    ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGWINCH");
  -	}
  +        ap_mpm_pod_killpg(pod, ap_daemons_limit);
  +
   #ifndef SCOREBOARD_FILE
   	/* This is mostly for debugging... so that we know what is still
   	    * gracefully dealing with existing request.  But we can't really
  
  
  

Mime
View raw message