Author: mturk
Date: Sun Jul 1 04:54:45 2007
New Revision: 552292
URL: http://svn.apache.org/viewvc?view=rev&rev=552292
Log:
Use shutdown instead hard close for connected sockets.
This ensures that the FIN will be send to the Tomcat thus
switching from CLOSE_WAIT to TIME_WAIT.
The rewritten shutdown_socket is basically Apache 1.3 linering_close.
It needs testing, but mine tests shows the large decrease in CLOSE_WAIT socket
states when connectionTimeout is set on Tomcat side.
Modified:
tomcat/connectors/trunk/jk/native/common/jk_ajp_common.c
tomcat/connectors/trunk/jk/native/common/jk_connect.c
Modified: tomcat/connectors/trunk/jk/native/common/jk_ajp_common.c
URL:
http://svn.apache.org/viewvc/tomcat/connectors/trunk/jk/native/common/jk_ajp_common.c?view=diff&rev=552292&r1=552291&r2=552292
==============================================================================
--- tomcat/connectors/trunk/jk/native/common/jk_ajp_common.c (original)
+++ tomcat/connectors/trunk/jk/native/common/jk_ajp_common.c Sun Jul 1
04:54:45 2007
@@ -681,7 +681,7 @@
static void ajp_reset_endpoint(ajp_endpoint_t * ae, jk_logger_t *l)
{
if (IS_VALID_SOCKET(ae->sd) && !ae->reuse) {
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG,
"reset socket with sd = %u", ae->sd );
@@ -720,11 +720,12 @@
{
int rc;
ajp_worker_t *aw = ae->worker;
- jk_sock_t sock = ae->sd;
+ jk_sock_t sock;
+ JK_ENTER_CS(&aw->cs, rc);
+ sock = ae->sd;
/* Mark existing endpoint socket as closed */
ae->sd = JK_INVALID_SOCKET;
- JK_ENTER_CS(&aw->cs, rc);
if (rc) {
unsigned int i;
for (i = 0; i < aw->ep_cache_sz; i++) {
@@ -739,7 +740,7 @@
}
/* Close previous socket */
if (IS_VALID_SOCKET(sock))
- jk_close_socket(sock);
+ jk_shutdown_socket(sock);
}
/*
@@ -1195,7 +1196,7 @@
jk_log(l, JK_LOG_DEBUG,
"(%s) socket %d is not connected any more (errno=%d)",
ae->worker->name, ae->sd, errno);
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
ae->sd = JK_INVALID_SOCKET;
err = 1;
}
@@ -1242,7 +1243,7 @@
jk_log(l, JK_LOG_ERROR,
"(%s) error sending request. Unrecoverable operation",
ae->worker->name);
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
ae->sd = JK_INVALID_SOCKET;
JK_TRACE_EXIT(l);
return JK_FALSE;
@@ -1291,7 +1292,7 @@
*/
if (ajp_connection_tcp_send_message(ae, op->request, l) !=
JK_TRUE) {
/* Close the socket if unable to send request */
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
ae->sd = JK_INVALID_SOCKET;
jk_log(l, JK_LOG_INFO,
"(%s) error sending request on a fresh connection
(errno=%d)",
@@ -1302,7 +1303,7 @@
}
else {
/* Close the socket if unable to connect */
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
ae->sd = JK_INVALID_SOCKET;
jk_log(l, JK_LOG_INFO,
"(%s) error connecting to the backend server (errno=%d)",
@@ -1336,7 +1337,7 @@
if (postlen > AJP_HEADER_LEN) {
if (ajp_connection_tcp_send_message(ae, op->post, l) != JK_TRUE) {
/* Close the socket if unable to send request */
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
ae->sd = JK_INVALID_SOCKET;
jk_log(l, JK_LOG_ERROR, "(%s) failed resending request body (%d)",
ae->worker->name, postlen);
@@ -1356,7 +1357,7 @@
if (postlen > AJP_HEADER_LEN) {
if (ajp_connection_tcp_send_message(ae, s->reco_buf, l) !=
JK_TRUE) {
/* Close the socket if unable to send request */
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
ae->sd = JK_INVALID_SOCKET;
jk_log(l, JK_LOG_ERROR,
"(%s) failed resending request body (lb mode) (%d)",
@@ -1406,7 +1407,7 @@
s->content_read = (jk_uint64_t)len;
if (ajp_connection_tcp_send_message(ae, op->post, l) != JK_TRUE) {
/* Close the socket if unable to send request */
- jk_close_socket(ae->sd);
+ jk_shutdown_socket(ae->sd);
ae->sd = JK_INVALID_SOCKET;
jk_log(l, JK_LOG_ERROR, "(%s) error sending request body",
ae->worker->name);
@@ -1751,7 +1752,7 @@
jk_log(l, JK_LOG_ERROR,
"(%s) Tomcat is down or network problems",
p->worker->name);
- jk_close_socket(p->sd);
+ jk_shutdown_socket(p->sd);
p->sd = JK_INVALID_SOCKET;
JK_TRACE_EXIT(l);
return JK_FALSE;
Modified: tomcat/connectors/trunk/jk/native/common/jk_connect.c
URL:
http://svn.apache.org/viewvc/tomcat/connectors/trunk/jk/native/common/jk_connect.c?view=diff&rev=552292&r1=552291&r2=552292
==============================================================================
--- tomcat/connectors/trunk/jk/native/common/jk_connect.c (original)
+++ tomcat/connectors/trunk/jk/native/common/jk_connect.c Sun Jul 1 04:54:45
2007
@@ -495,14 +495,13 @@
#else
return close(s);
#endif
-
return -1;
}
#ifndef MAX_SECS_TO_LINGER
-#define MAX_SECS_TO_LINGER 16
+#define MAX_SECS_TO_LINGER 30
#endif
-#define SECONDS_TO_LINGER 1
+#define SECONDS_TO_LINGER 2
#ifndef SHUT_WR
#ifdef SD_SEND
@@ -513,15 +512,12 @@
#endif
int jk_shutdown_socket(jk_sock_t s)
{
- unsigned char dummy[512];
- int nbytes;
- int ttl = 0;
+ char dummy[512];
int rc = 0;
-#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
- int tmout = SECONDS_TO_LINGER * 1000;
-#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO)
+ fd_set rs;
struct timeval tv;
-#endif
+ time_t start = time(NULL);
+
if (!IS_VALID_SOCKET(s))
return -1;
@@ -531,29 +527,41 @@
if (shutdown(s, SHUT_WR)) {
return jk_close_socket(s);
}
-#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
- if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
- (const char *) &tmout, sizeof(int)) == 0)
- rc = 1;
-#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO)
- tv.tv_sec = SECONDS_TO_LINGER;
- tv.tv_usec = 0;
- if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
- (const void *) &tv, sizeof(tv)))
- rc = 1;
+
+ /* Set up to wait for readable data on socket... */
+ FD_ZERO(&rs);
+
+ do {
+ /* Read all data from the peer until we reach "end-of-file"
+ * (FIN from peer) or we've exceeded our overall timeout. If the
+ * backend does not send us bytes within 2 seconds
+ * (a value pulled from Apache 1.3 which seems to work well),
+ * close the connection.
+ */
+ FD_SET(s, &rs);
+ tv.tv_sec = SECONDS_TO_LINGER;
+ tv.tv_usec = 0;
+
+ if (select((int)s + 1, &rs, NULL, NULL, &tv) > 0) {
+ do {
+#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
+ rc = recv(s, &dummy[0], sizeof(dummy), 0);
+ /* Assuming SOCKET_ERROR is -1 on NETWARE too */
+ if (rc == SOCKET_ERROR)
+ errno = WSAGetLastError() - WSABASEERR;
+#else
+ rc = read(s, &dummy[0], sizeof(dummy));
#endif
- /* Read all data from the peer until we reach "end-of-file" (FIN
- * from peer) or we've exceeded our overall timeout. If the client does
- * not send us bytes within 16 second, close the connection.
- */
- while (rc) {
- nbytes = jk_tcp_socket_recvfull(s, dummy, sizeof(dummy));
- if (nbytes <= 0)
- break;
- ttl += SECONDS_TO_LINGER;
- if (ttl > MAX_SECS_TO_LINGER)
+ } while (rc == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (rc <= 0)
+ break;
+ }
+ else
break;
- }
+
+ } while (difftime(time(NULL), start) < MAX_SECS_TO_LINGER);
+
return jk_close_socket(s);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]