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