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);