Mercurial > dovecot > core-2.2
changeset 19960:5f32b22684ee
lib-http: client: Fixed handling of stalled connections that emerge when the client ioloop hasn't run for a long time.
Inside the peer's request handler routine, the connections are verified
after the ioloop continues. If they turn out to be broken, they
self-destruct while the handler routine is active, leading to problems.
Solved by referencing the connection and retrying the connection statistics
loop when a connection is lost in the process.
author | Stephan Bosch <stephan@rename-it.nl> |
---|---|
date | Fri, 25 Mar 2016 02:47:28 +0900 |
parents | 9d1ca7caf268 |
children | 3f6a74b9ce54 |
files | src/lib-http/http-client-peer.c |
diffstat | 1 files changed, 20 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/http-client-peer.c Fri Mar 25 00:45:54 2016 +0900 +++ b/src/lib-http/http-client-peer.c Fri Mar 25 02:47:28 2016 +0900 @@ -275,17 +275,22 @@ peer->handling_requests = TRUE; t_array_init(&conns_avail, array_count(&peer->conns)); do { + bool conn_lost = FALSE; + array_clear(&conns_avail); connecting = closing = idle = 0; /* gather connection statistics */ array_foreach(&peer->conns, conn_idx) { - if (http_client_connection_is_ready(*conn_idx)) { + struct http_client_connection *conn = *conn_idx; + + http_client_connection_ref(conn); + if (http_client_connection_is_ready(conn)) { struct _conn_available *conn_avail; unsigned int insert_idx, pending_requests; /* compile sorted availability list */ - pending_requests = http_client_connection_count_pending(*conn_idx); + pending_requests = http_client_connection_count_pending(conn); if (array_count(&conns_avail) == 0) { insert_idx = 0; } else { @@ -298,18 +303,28 @@ } } conn_avail = array_insert_space(&conns_avail, insert_idx); - conn_avail->conn = *conn_idx; + conn_avail->conn = conn; conn_avail->pending_requests = pending_requests; if (pending_requests == 0) idle++; } + if (!http_client_connection_unref(&conn)) { + conn_lost = TRUE; + break; + } + conn = *conn_idx; /* count the number of connecting and closing connections */ - if ((*conn_idx)->closing) + if (conn->closing) closing++; - else if (!(*conn_idx)->connected) + else if (!conn->connected) connecting++; } + if (conn_lost) { + /* connection array changed while iterating; retry */ + continue; + } + working_conn_count = array_count(&peer->conns) - closing; statistics_dirty = FALSE;