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]

Reply via email to