Mercurial > dovecot > core-2.2
changeset 17857:adcf35ac5432
lib-http: client: Fixed aborting request in the middle of sending payload.
If the request payload is so big that it cannot be sent all at once, the
caller may at some point abort the request when it is still being sent. The
bug occurred when the request finally finished sending. It erroneously
advanced the state to WAITING rather than remaining ABORTED, thus
'reviving' the request unexpectedly.
author | Stephan Bosch <stephan@rename-it.nl> |
---|---|
date | Wed, 01 Oct 2014 10:33:39 +0300 |
parents | df53b5ccc2ba |
children | 548cb71d63da |
files | src/lib-http/http-client-connection.c src/lib-http/http-client-request.c |
diffstat | 2 files changed, 12 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/http-client-connection.c Wed Oct 01 00:17:09 2014 +0300 +++ b/src/lib-http/http-client-connection.c Wed Oct 01 10:33:39 2014 +0300 @@ -299,6 +299,7 @@ if (conn->peer->no_payload_sync) req->payload_sync = FALSE; + i_assert(req->state == HTTP_REQUEST_STATE_QUEUED); array_append(&conn->request_wait_list, &req, 1); http_client_request_ref(req);
--- a/src/lib-http/http-client-request.c Wed Oct 01 00:17:09 2014 +0300 +++ b/src/lib-http/http-client-request.c Wed Oct 01 10:33:39 2014 +0300 @@ -453,14 +453,23 @@ { i_assert(req->conn != NULL); + /* drop payload output stream */ if (req->payload_output != NULL) { o_stream_unref(&req->payload_output); req->payload_output = NULL; } - req->state = HTTP_REQUEST_STATE_WAITING; + + /* advance state only when request didn't get aborted in the mean time */ + if (req->state != HTTP_REQUEST_STATE_ABORTED) { + i_assert(req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT); + req->state = HTTP_REQUEST_STATE_WAITING; + } + + /* release connection */ req->conn->output_locked = FALSE; - http_client_request_debug(req, "Finished sending payload"); + http_client_request_debug(req, "Finished sending%s payload", + (req->state == HTTP_REQUEST_STATE_ABORTED ? " aborted" : "")); } static int