Mercurial > dovecot > core-2.2
changeset 20355:6335d6256a58
lib-http: client: Fixed bug in handling of lost connections while returning from another ioloop.
At one instance the http_client_connection_is_ready() function could have destroyed the connection while the caller still depended on it.
Renamed the http_client_connection_is_ready() function to http_client_connection_check_ready().
This now returns -1 when the connection got destroyed. Before it returned a bool that just indicated whether the connection was ready or not.
So, there is no need anymore to preserve a connection reference while calling this function.
author | Stephan Bosch <stephan@dovecot.fi> |
---|---|
date | Wed, 25 May 2016 23:41:47 +0200 |
parents | adfa1b7fea65 |
children | 3073a9e2ab8a |
files | src/lib-http/http-client-connection.c src/lib-http/http-client-peer.c src/lib-http/http-client-private.h |
diffstat | 3 files changed, 21 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/http-client-connection.c Mon May 23 02:38:49 2016 +0200 +++ b/src/lib-http/http-client-connection.c Wed May 25 23:41:47 2016 +0200 @@ -235,7 +235,7 @@ http_client_connection_close(_conn); } -bool http_client_connection_is_ready(struct http_client_connection *conn) +int http_client_connection_check_ready(struct http_client_connection *conn) { int ret; @@ -245,14 +245,14 @@ this way, but theoretically we could, although that would add quite a bit of complexity. */ - return FALSE; + return 0; } if (!conn->connected || conn->output_locked || conn->output_broken || conn->close_indicated || conn->tunneling || http_client_connection_count_pending(conn) >= conn->client->set.max_pipelined_requests) - return FALSE; + return 0; if (conn->last_ioloop != NULL && conn->last_ioloop != current_ioloop) { conn->last_ioloop = current_ioloop; @@ -270,10 +270,10 @@ stream_errno != 0 ? i_stream_get_error(conn->conn.input) : "EOF")); - return FALSE; + return -1; } } - return TRUE; + return 1; } static void @@ -408,10 +408,14 @@ struct http_client_request *req = NULL; const char *error; bool pipelined; + int ret; - if (!http_client_connection_is_ready(conn)) { - http_client_connection_debug(conn, "Not ready for next request"); - return 0; + if ((ret=http_client_connection_check_ready(conn)) <= 0) { + if (ret == 0) { + http_client_connection_debug(conn, + "Not ready for next request"); + } + return ret; } /* claim request, but no urgent request can be second in line */ @@ -552,7 +556,6 @@ } conn->incoming_payload = NULL; - http_client_connection_ref(conn); /* input stream may have pending input. make sure input handler gets called (but don't do it directly, since we get get here @@ -565,10 +568,8 @@ } /* room for new requests */ - if (http_client_connection_is_ready(conn)) + if (http_client_connection_check_ready(conn) > 0) http_client_peer_trigger_request_handler(conn->peer); - - http_client_connection_unref(&conn); } static bool @@ -966,7 +967,7 @@ conn->peer->allows_pipelining = TRUE; /* room for new requests */ - if (http_client_connection_is_ready(conn)) + if (http_client_connection_check_ready(conn) > 0) http_client_peer_trigger_request_handler(conn->peer); } } @@ -1025,7 +1026,7 @@ } if (!conn->output_locked) { /* room for new requests */ - if (http_client_connection_is_ready(conn)) + if (http_client_connection_check_ready(conn) > 0) http_client_peer_trigger_request_handler(conn->peer); } }
--- a/src/lib-http/http-client-peer.c Mon May 23 02:38:49 2016 +0200 +++ b/src/lib-http/http-client-peer.c Wed May 25 23:41:47 2016 +0200 @@ -268,9 +268,12 @@ /* gather connection statistics */ array_foreach(&peer->conns, conn_idx) { struct http_client_connection *conn = *conn_idx; + int ret; - http_client_connection_ref(conn); - if (http_client_connection_is_ready(conn)) { + if ((ret=http_client_connection_check_ready(conn)) < 0) { + conn_lost = TRUE; + break; + } else if (ret > 0) { struct _conn_available *conn_avail; unsigned int insert_idx, pending_requests; @@ -293,11 +296,6 @@ 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->closing) closing++;
--- a/src/lib-http/http-client-private.h Mon May 23 02:38:49 2016 +0200 +++ b/src/lib-http/http-client-private.h Wed May 25 23:41:47 2016 +0200 @@ -325,7 +325,7 @@ struct http_client_connection *conn); unsigned int http_client_connection_count_pending(struct http_client_connection *conn); -bool http_client_connection_is_ready(struct http_client_connection *conn); +int http_client_connection_check_ready(struct http_client_connection *conn); bool http_client_connection_is_idle(struct http_client_connection *conn); int http_client_connection_next_request(struct http_client_connection *conn); void http_client_connection_check_idle(struct http_client_connection *conn);