Mercurial > dovecot > core-2.2
changeset 22213:f8d4ae988e7f
lib-http: client: When a request is destroyed prematurely during payload input, consider the payload stream destroyed and act accordingly.
The application may hold a reference to the payload stream still, and it may be difficult to prevent that.
This causes lib-http to keep waiting for the payload to be destroyed.
When nothing else is going on, the current ioloop may then become empty, which caused the familiar assert failure.
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Wed, 24 May 2017 21:59:32 +0200 |
parents | 8cc50c161f4a |
children | 1b4a0735b158 |
files | src/lib-http/http-client-connection.c |
diffstat | 1 files changed, 20 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/http-client-connection.c Wed May 24 19:08:43 2017 +0200 +++ b/src/lib-http/http-client-connection.c Wed May 24 21:59:32 2017 +0200 @@ -646,7 +646,7 @@ void http_client_connection_request_destroyed( struct http_client_connection *conn, struct http_client_request *req) { - struct istream *payload = conn->incoming_payload; + struct istream *payload; i_assert(req->conn == conn); if (conn->pending_request != req) @@ -655,10 +655,28 @@ http_client_connection_debug(conn, "Pending request destroyed prematurely"); - if (payload == NULL) + payload = conn->incoming_payload; + if (payload == NULL) { + /* payload already gone */ return; + } + + /* destroy the payload, so that the timeout istream is closed */ i_stream_ref(payload); i_stream_destroy(&payload); + + payload = conn->incoming_payload; + if (payload == NULL) { + /* not going to happen, but check for it anyway */ + return; + } + + /* the application still holds a reference to the payload stream, but it + is closed and we don't care about it anymore, so act as though it is + destroyed. */ + i_stream_remove_destroy_callback(payload, + http_client_payload_destroyed); + http_client_payload_destroyed(req); } static bool