Re: Livelock bug in conn_pool_get()/http.c
Alexander Malysh <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
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