Livelock bug in conn_pool_get()/http.c

"Paul Keogh" <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Hi,

I've experienced a livelock (ie. CPU bound) bug in the conn_pool_get()
function in http.c.

I'm sending lots of HTTP requests to a server that closes the connection
after every request.
After 5/6/7 requests the conn_pool_get() function gets stuck in an
infinite look and never returns;

>From looking at the code;

    do {
        retry = 0;
        key = conn_pool_key(host, port);
        mutex_lock(conn_pool_lock);
        list = dict_get(conn_pool, key);
        if (list != NULL)
            conn = gwlist_extract_first(list);
        mutex_unlock(conn_pool_lock);
        /*
         * Note: we don't hold conn_pool_lock when we
check/destroy/unregister
         *       connection because otherwise we can deadlock! And it's
even better
         *       not to delay other threads while we check connection.
         */
        if (conn != NULL) {
#ifdef USE_KEEPALIVE
            /* unregister our server disconnect callback */
            conn_unregister(conn);
#endif 
            /*
             * Check whether the server has closed the connection while
             * it has been in the pool.
             */
            conn_wait(conn, 0);
            if (conn_eof(conn) || conn_error(conn)) {
                debug("gwlib.http", 0, "HTTP:conn_pool_get: Server
closed connection, destroying it <%s><%p><fd:%d>.",
                      octstr_get_cstr(key), conn, conn_get_id(conn));
                conn_destroy(conn);
                retry = 1;
                conn = NULL;
            }
        }
        octstr_destroy(key);
    } while(retry == 1);

* The retry variable is set to 1 because the server has closed the
connection

* This forces the while loop to run

* There are no conns in the list for this host/port combination so conn
is always NULL subsequently. The
retry variable is not reset to 0 on this condition and the loop locks
up.

* One solution is to reset retry to 0 on a NULL conn - 

        if (conn != NULL) {
#ifdef USE_KEEPALIVE
		....
	  }
	  else
            retry = 0;

This does appear to fix the issue in my test harness.

Comments ?
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.