You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by st...@apache.org on 2002/11/12 23:44:07 UTC

cvs commit: apache-1.3/src/main alloc.c

stoddard    2002/11/12 14:44:07

  Modified:    src      CHANGES
               src/main alloc.c
  Log:
  Update timeout algorithm in free_proc_chain.  Try polling the existing subprocess
  a few times before going into a 3 second sleep. Often we find that the subprocess
  will exit within milliseconds.
  
  Revision  Changes    Path
  1.1861    +8 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1860
  retrieving revision 1.1861
  diff -u -r1.1860 -r1.1861
  --- CHANGES	12 Nov 2002 19:59:15 -0000	1.1860
  +++ CHANGES	12 Nov 2002 22:44:05 -0000	1.1861
  @@ -1,4 +1,12 @@
   Changes with Apache 1.3.28
  +  *) Update timeout algorithm in free_proc_chain. If a subprocess
  +     did not exit immediately, the thread would sleep for 3 seconds
  +     before checking the subprocess exit status again. In a very
  +     common case when the subprocess was an HTTP server CGI script,
  +     the CGI script actually exited a fraction of a second into the 3
  +     second sleep, which effectively limited the server to serving one 
  +     CGI request every 3 seconds across a persistent connection.
  +     PRs 6961, 8664 [Bill Stoddard]
   
     *) mod_setenvif: Add SERVER_ADDR special keyword to allow
        envariable setting according to the server IP address
  
  
  
  1.129     +50 -7     apache-1.3/src/main/alloc.c
  
  Index: alloc.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/main/alloc.c,v
  retrieving revision 1.128
  retrieving revision 1.129
  diff -u -r1.128 -r1.129
  --- alloc.c	7 Sep 2002 22:57:05 -0000	1.128
  +++ alloc.c	12 Nov 2002 22:44:06 -0000	1.129
  @@ -2624,15 +2624,28 @@
       return pid;
   }
   
  +
  +/* 
  + * Timing constants for killing subprocesses
  + * There is a total 3-second delay between sending a SIGINT 
  + * and sending of the final SIGKILL.
  + * TIMEOUT_INTERVAL should be set to TIMEOUT_USECS / 64
  + * for the exponetial timeout alogrithm.
  + */
  +#define TIMEOUT_USECS    3000000
  +#define TIMEOUT_INTERVAL   46875
  +
   static void free_proc_chain(struct process_chain *procs)
   {
       /* Dispose of the subprocesses we've spawned off in the course of
        * whatever it was we're cleaning up now.  This may involve killing
        * some of them off...
        */
  -
  +    struct timeval tv;
       struct process_chain *p;
       int need_timeout = 0;
  +    int timeout_interval;
  +    int exit_int;
       int status;
   
       if (procs == NULL)
  @@ -2694,18 +2707,49 @@
   	if ((p->kill_how == kill_after_timeout)
   	    || (p->kill_how == kill_only_once)) {
   	    /* Subprocess may be dead already.  Only need the timeout if not. */
  -	    if (ap_os_kill(p->pid, SIGTERM) != -1)
  +	    if (ap_os_kill(p->pid, SIGTERM) == -1) {
  +                p->kill_how = kill_never;
  +            }
  +            else {
   		need_timeout = 1;
  +            }
   	}
   	else if (p->kill_how == kill_always) {
   	    kill(p->pid, SIGKILL);
   	}
       }
   
  -    /* Sleep only if we have to... */
  -
  -    if (need_timeout)
  -	sleep(3);
  +    /* Sleep only if we have to. The sleep algorithm grows
  +     * by a factor of two on each iteration. TIMEOUT_INTERVAL
  +     * is equal to TIMEOUT_USECS / 64.
  +     */
  +    if (need_timeout) {
  +        timeout_interval = TIMEOUT_INTERVAL;
  +        tv.tv_sec = 0;
  +        tv.tv_usec = timeout_interval;
  +        select(0, NULL, NULL, NULL, &tv);
  +
  +        do {
  +            need_timeout = 0;
  +            for (p = procs; p; p = p->next) {
  +                if (p->kill_how == kill_after_timeout) {
  +                    if (waitpid(p->pid, (int *) 0, WNOHANG | WUNTRACED) > 0)
  +                        p->kill_how = kill_never;
  +                    else
  +                        need_timeout = 1;
  +                }
  +            }
  +            if (need_timeout) {
  +                if (timeout_interval >= TIMEOUT_USECS) {
  +                    break;
  +                }
  +                tv.tv_sec = timeout_interval / 1000000;
  +                tv.tv_usec = timeout_interval % 1000000;
  +                select(0, NULL, NULL, NULL, &tv);
  +                timeout_interval *= 2;
  +            }
  +        } while (need_timeout);
  +    }
   
       /* OK, the scripts we just timed out for have had a chance to clean up
        * --- now, just get rid of them, and also clean up the system accounting
  @@ -2713,7 +2757,6 @@
        */
   
       for (p = procs; p; p = p->next) {
  -
   	if (p->kill_how == kill_after_timeout)
   	    kill(p->pid, SIGKILL);