Return-Path: Delivered-To: apmail-httpd-dev-archive@httpd.apache.org Received: (qmail 83054 invoked by uid 500); 16 Dec 2002 19:50:59 -0000 Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list dev@httpd.apache.org Received: (qmail 83041 invoked from network); 16 Dec 2002 19:50:58 -0000 Subject: Re: cvs commit: apache-1.3/src/main alloc.c To: dev@httpd.apache.org X-Mailer: Lotus Notes Release 5.0.7 March 21, 2001 Message-ID: From: "David McCreedy" Date: Mon, 16 Dec 2002 12:49:42 -0700 X-MIMETrack: Serialize by Router on d27ml602/27/M/IBM(Release 5.0.11 |July 24, 2002) at 12/16/2002 01:51:00 PM MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N Can these added "select" calls be changed to "ap_select"? That way the ap_select #define's in ap_config.h will get applied. Sorry for the late feedback. -David stoddard@apache.o rg To: apache-1.3-cvs@apache.org cc: 11/12/2002 03:44 Subject: cvs commit: apache-1.3/src/main alloc.c PM Please respond to dev 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);