[tbnl-devel] Socket leaks, again
Edi Weitz
edi at agharta.de
Sun Jul 18 15:37:11 UTC 2004
[Again, I'm in a train and sending via cell phone and GPRS. Let's see
if it works better this time. Also, I'm not sure if SquirrelMail will
be able to keep indentations.]
I'm prepared to make myself a fool in public again. I've debugged the
mod_lisp/Apache interaction (by inserting log statements in strategic
places) a bit and here's what I found out (Linux x86, mod_lisp 2.33,
Apache 1.3.29, CMUCL 18e):
1. Whenever OpenLispSocket is called, cfg->LispSocket is 0. This can
be best seen if you start Apache with the -X option so that you
only one child process. This would imply that sockets can never be
re-used.
2. Another data point (see also Peter's earlier post) is that
netstat -an | grep 3000
reports far more established connections than there are Apache
child processes.
3. I guess this is due to the fact that the configuration record is
reset by Apache on each request. I observe that the comment in
Apache's example module (which is also in mod_lisp) says
"Note that while the per-directory and per-server configuration
records are available to most of the module handlers, they
should be treated as READ-ONLY by all except the command and
merge handlers. Sometimes handlers are handed a record that
applies to the current location by implication or inheritance,
and modifying it will change the rules for other locations."
This is obviously violated by mod_lisp which modifies the record in
the content handler.
4. My naïve attempt to fix this is to make LispSocket and
UnsafeLispSocket global variables. A patch which reflects my
changes is attached at the bottom. This currently works for
me. Debugging shows that sockets are in fact re-used this
time. Also, if I benchmark with ApacheBench (2000 request, 200
concurrent, 1300 byte static page, client and server on same
machine) then the original mod_lisp code is able to handle roughly
140 requests per seconds while my modified code handles more than
460 requests per seconds.
5. Of course, this patch will only work if the Apache children are
separate processes spawned by the server process as with Apache
1.3, i.e. another approach must be taken for the new, alternative
Apache 2.0 thread implementations.
OK, that's all for now. Let me know what you think.
Cheers,
Edi.
--- /home/edi/downloads/Lisp/mod_lisp-2.33.c 2004-07-16 01:52:23.000000000
+0200
+++ mod_lisp-2.33.c 2004-07-18 16:58:23.000000000 +0200
@@ -189,10 +189,11 @@
char LispServerIP[20];
long LispServerPort;
char LispServerId[100];
- long LispSocket;
- long UnsafeLispSocket;
} excfg;
+static long LispSocket = 0;
+static long UnsafeLispSocket = 0;
+
pool *SocketPool = NULL;
/*
@@ -371,13 +372,6 @@
if (lisp_pool == NULL) {
lisp_pool = ap_make_sub_pool(NULL);
};
- /*
- * Likewise for the table of routine/environment pairs we visit
outside of
- * request context.
- */
- if (static_calls_made == NULL) {
- static_calls_made = ap_make_table(lisp_pool, 16);
- };
}
#endif
@@ -421,21 +415,21 @@
int ret;
#ifndef WIN32
- if (cfg->LispSocket)
- if (cfg->UnsafeLispSocket)
+ if (LispSocket)
+ if (UnsafeLispSocket)
{
- ap_pclosesocket(SocketPool, cfg->LispSocket);
- cfg->LispSocket = 0;
- cfg->UnsafeLispSocket = 0;
+ ap_pclosesocket(SocketPool, LispSocket);
+ LispSocket = 0;
+ UnsafeLispSocket = 0;
}
else
{
- return cfg->LispSocket;
+ return LispSocket;
}
#endif
- cfg->LispSocket = 0;
- cfg->UnsafeLispSocket = 0;
+ LispSocket = 0;
+ UnsafeLispSocket = 0;
addr.sin_addr.s_addr = inet_addr(cfg->LispServerIP);
addr.sin_port = htons((unsigned short) cfg->LispServerPort);
addr.sin_family = AF_INET;
@@ -459,7 +453,7 @@
if (ret == -1)
return -1;
- cfg->LispSocket = sock;
+ LispSocket = sock;
return sock;
}
@@ -498,13 +492,13 @@
if (Socket != -1)
ap_pclosesocket(SocketPool, Socket);
#else
- if (!cfg->LispSocket)
+ if (!LispSocket)
return;
- ap_pclosesocket(SocketPool, cfg->LispSocket);
+ ap_pclosesocket(SocketPool, LispSocket);
- cfg->LispSocket = 0;
- cfg->UnsafeLispSocket = 0;
+ LispSocket = 0;
+ UnsafeLispSocket = 0;
#endif
}
@@ -605,7 +599,7 @@
}
ap_reset_timeout(r);
- dcfg->UnsafeLispSocket = 1;
+ UnsafeLispSocket = 1;
if (r->subprocess_env)
{
@@ -860,7 +854,7 @@
ap_bpushfd(BuffSocket, -1, -1); /* unlink buffer to keep socket */
BuffSocket->flags &= ~B_SOCKET;
}
- dcfg->UnsafeLispSocket = 0;
+ UnsafeLispSocket = 0;
return OK;
}
@@ -985,7 +979,6 @@
strcpy(cfg->LispServerId, "apache");
cfg->LispServerPort = 3000;
cfg->DefaultLispServer = 1;
- cfg->LispSocket = 0;
cfg->cmode = CONFIG_MODE_DIRECTORY;
dname = (dname != NULL) ? dname : "";
@@ -1059,7 +1052,6 @@
merged_config->DefaultLispServer = 1;
}
- merged_config->LispSocket = 0;
return (void *) merged_config;
}
@@ -1087,7 +1079,6 @@
strcpy(cfg->LispServerIP, "127.0.0.1");
strcpy(cfg->LispServerId, "apache");
cfg->LispServerPort = 3000;
- cfg->LispSocket = 0;
cfg->DefaultLispServer = 1;
sname = (sname != NULL) ? sname : "";
cfg->loc = ap_pstrcat(p, "SVR(", sname, ")", NULL);
@@ -1148,7 +1139,6 @@
merged_config->DefaultLispServer = 1;
}
- merged_config->LispSocket = 0;
return (void *) merged_config;
}
@@ -1309,7 +1299,6 @@
cfg->LispServerId[99] = 0;
cfg->LispServerPort = atoi(port);
cfg->DefaultLispServer = 0;
- cfg->LispSocket = 0;
return NULL;
}
More information about the Tbnl-devel
mailing list