Mercurial > dovecot > core-2.2
changeset 17876:ecb0ba0ce02f
lib-http: client: Fixed problem occuring when a nested ioloop was run inside a request callback using the same client.
If requests in the nested ioloop would use the same connection as the one
that called the callback, the requests would (in the best scenario) all be
doomed to time out.
author | Stephan Bosch <stephan@rename-it.nl> |
---|---|
date | Sat, 04 Oct 2014 17:30:54 +0300 |
parents | dd25099bd633 |
children | 9ce4d8d394cc |
files | src/lib-http/http-client-connection.c src/lib-http/http-client-private.h |
diffstat | 2 files changed, 16 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/http-client-connection.c Sat Oct 04 00:29:30 2014 +0300 +++ b/src/lib-http/http-client-connection.c Sat Oct 04 17:30:54 2014 +0300 @@ -53,13 +53,22 @@ { unsigned int pending_count = array_count(&conn->request_wait_list); - if (conn->pending_request != NULL) + if (conn->in_req_callback || conn->pending_request != NULL) pending_count++; return pending_count; } bool http_client_connection_is_ready(struct http_client_connection *conn) { + if (conn->in_req_callback) { + /* this can happen when a nested ioloop is created inside request + callback. we currently don't reuse connections that are occupied + this way, but theoretically we could, although that would add + quite a bit of complexity. + */ + return FALSE; + } + return (conn->connected && !conn->output_locked && !conn->close_indicated && !conn->tunneling && http_client_connection_count_pending(conn) < @@ -184,6 +193,7 @@ if (conn->connected && array_is_created(&conn->request_wait_list) && array_count(&conn->request_wait_list) == 0 && + !conn->in_req_callback && conn->incoming_payload == NULL && conn->client->set.max_idle_time_msecs > 0) { @@ -437,6 +447,7 @@ struct istream *payload; bool retrying; + i_assert(!conn->in_req_callback); i_assert(conn->incoming_payload == NULL); i_assert(conn->pending_request == NULL); @@ -459,10 +470,12 @@ if (conn->to_requests != NULL) timeout_remove(&conn->to_requests); } - + + conn->in_req_callback = TRUE; http_client_connection_ref(conn); retrying = !http_client_request_callback(req, response); http_client_connection_unref(&conn); + conn->in_req_callback = FALSE; if (conn == NULL) { /* the callback managed to get this connection destroyed */ if (!retrying)
--- a/src/lib-http/http-client-private.h Sat Oct 04 00:29:30 2014 +0300 +++ b/src/lib-http/http-client-private.h Sat Oct 04 17:30:54 2014 +0300 @@ -142,6 +142,7 @@ unsigned int output_locked:1; /* output is locked; no pipelining */ unsigned int payload_continue:1; /* received 100-continue for current request */ + unsigned int in_req_callback:1; /* performin request callback (busy) */ }; struct http_client_peer {