cURL / Mailing Lists / curl-library / Single Mail

curl-library

cleanup half closed sockets in connection cache

From: Frank Meier <f.meier_at_phion.com>
Date: Mon, 12 Oct 2009 18:33:51 +0200

hi

i've experienced the problem, that curl is not aware of connections that are being closed from the peer. So if the Webserver closes the TCP connection after the keepalive timeout (some secconds), the socket will remain in close_wait state, until the next curl request ist issued. Of course I understand the reason, since my application is already doing something else when the connection closes, there is just no code that calls close() on that socket.

I now liked to change that behavior, and didn't find a nice solution. First I wanted to remeber the sockets and then close it if I see that the socket has been closed by the peer. but this would bypass libcurl, and imho would be a hack.
After further searching I've found a posting in this mailing list, dealing with a similiar problem:
http://curl.haxx.se/mail/lib-2009-03/0009.html
the patch included in this post removed all connections in close_wait before a new request, but still there will be at least one (the last) connection, that will remain in close_wait state "forever".

I now would propose a cleanup fuction which goes throuh the connection cache an removes and closes all connections, which are not usable anymore. Based on the code in ConnectionExists() in url.c I came up with something like the following:

/*
 * This function iterates through a given connection cache, and closes
 * all sockets which are not usable anymore (eg. in close_wait state)
 */
void Curl_close_dead_connections(struct conncache *connc)
{
        long i;
        struct connectdata *check;

        for(i=0; i< connc->num; i++) {
                bool match = FALSE;
                size_t pipeLen = 0;

                check = connc->connects[i];
                if(!check)
                        /* NULL pointer means not filled-in entry */
                        continue;

                pipeLen = check->send_pipe->size + check->recv_pipe->size;

                if(check->connectindex == -1) {
                        check->connectindex = i; /* Set this appropriately since it might have
                        been set to -1 when the easy was removed
                        from the multi */
                }

                if(!pipeLen && !check->inuse) {
                         /* The check for a dead socket makes sense only if there are no
                        handles in pipeline and the connection isn't already marked in
                        use */
                        bool dead = SocketIsDead(check->sock[FIRSTSOCKET]);
                        if(dead) {
                                Curl_disconnect(check); /* disconnect resources */
                                connc->connects[i]=NULL; /* nothing here */
                        }
                }
        }
}

Did I miss something to deal with this problem, or are there other ideas? feedback is appreciated.

cheers, Frank
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2009-10-12