Hi Paul,

Paul Keogh schrieb:
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;

hmm, this should be something different.


From looking at the code;

    do {
        retry = 0;
        ˆˆˆˆˆˆˆˆˆˆˆˆ
here we reset retry... and when no conns in dict found than no retry will be performed.

        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


right

* This forces the while loop to run

right


* 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.

not true. see above...


* 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 ?


I don't know why this change should help. could you please try debug it further?







Thanks,
Alex


Reply via email to