Attached is my redo of the patch for flood_net.c explained below:

-Norman Tuttle, developer, OpenDemand Systems [EMAIL PROTECTED]

On Thu, 16 Oct 2003, Norman Tuttle wrote:

> This patch makes the open_socket() function non-recursive, providing the 
> benefits of iterative functions in terms of performance, also replacing 
> the close_socket (same level) reference with the lower level 
> apr_socket_close(), since this would reserve close_socket() for a case 
> where the open_socket() successfully occurred. This socket closure now 
> also occurs in the case where a socket is to be reopened in the case of 
> TIME_WAIT exhaustion, which was the recursive condition. Please examine 
> and apply this change, which was made to the current CVS tree, without 
> reference to my former submission.



--- \flood-1.1\flood_net.c      2003-09-09 05:49:50.000000000 -0400
+++ flood_net.c 2003-11-03 11:31:14.000000000 -0500
@@ -58,6 +58,8 @@
 #include "flood_profile.h"
 #include "flood_net.h"
 
+#define FOUR_MIN (4*60*APR_USEC_PER_SEC)
+
 /* Open the TCP connection to the server */
 flood_socket_t* open_socket(apr_pool_t *pool, request_t *r,
                             apr_status_t *status)
@@ -70,49 +72,32 @@
 
     if ((rv = apr_sockaddr_info_get(&destsa, r->parsed_uri->hostname, 
APR_INET, 
                                     r->parsed_uri->port, 0, pool)) 
-                                    != APR_SUCCESS) {
-        if (status) {
-            *status = rv;
-        }
-        return NULL;
-    }
-
-    if ((rv = apr_socket_create(&fs->socket, APR_INET, SOCK_STREAM,
-                                APR_PROTO_TCP, pool)) != APR_SUCCESS) {
-        if (status) {
-            *status = rv;
-        }
-        return NULL;
-    }
-
-    if ((rv = apr_socket_connect(fs->socket, destsa)) != APR_SUCCESS) {
-        if (APR_STATUS_IS_EINPROGRESS(rv)) {
-            /* FIXME: Handle better */
-            close_socket(fs);
-            if (status) {
-                *status = rv;
-            }
-            return NULL;
-        }
-        else if (APR_STATUS_IS_EAGAIN(rv))
+                                    == APR_SUCCESS) do { /* goal of do-loop is
+      to get past EAGAIN error so we need a 0 (APR_SUCCESS) status to pass */
+      if ((rv = apr_socket_create(&fs->socket, APR_INET, SOCK_STREAM,
+                                  APR_PROTO_TCP, pool)) != APR_SUCCESS) break;
+      if ((rv = apr_socket_connect(fs->socket, destsa)) != APR_SUCCESS) {
+        apr_socket_close(fs->socket); /* If we have created socket and cannot
+        connect it (including on reopen), we should now destroy the socket */
+        if (APR_STATUS_IS_EAGAIN(rv))
         {
             /* We have run out of ports available due to TIME_WAIT exhaustion.
              * Sleep for four minutes, and try again. 
              * Note: Solaris returns EADDRNOTAVAIL, Linux returns EAGAIN.
              * XXX: Then APR'IZE THIS ALREADY
              */
-            apr_sleep(4 * 60 * APR_USEC_PER_SEC);
-            return open_socket(pool, r, status);
+            apr_sleep(FOUR_MIN);
         }
-        else
-        {
-            /* FIXME: Handle */
-            close_socket(fs);
-            if (status) {
-                *status = rv;
-            }
-            return NULL;
+        else break; /* Includes APR_STATUS_IS_EINPROGRESS with other errors,
+                     * will exit while loop & func with an error status */
+      }
+    } while (rv);
+    if (rv)
+    {
+        if (status) {
+            *status = rv;
         }
+        return (flood_socket_t *)(fs->socket = NULL);
     }
 
     apr_socket_opt_set(fs->socket, APR_SO_TIMEOUT, LOCAL_SOCKET_TIMEOUT);

Reply via email to