changeset 22212:8cc50c161f4a

lib-http: client: Explicitly destroy the response payload timeout stream when the request is destroyed while receiving payload. This way, the timeout is stopped. This caused ioloop panics.
author Stephan Bosch <stephan.bosch@dovecot.fi>
date Wed, 24 May 2017 19:08:43 +0200
parents e7239fd6301f
children f8d4ae988e7f
files src/lib-http/http-client-connection.c src/lib-http/http-client-private.h src/lib-http/http-client-request.c
diffstat 3 files changed, 24 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-http/http-client-connection.c	Tue May 30 18:25:50 2017 +0300
+++ b/src/lib-http/http-client-connection.c	Wed May 24 19:08:43 2017 +0200
@@ -643,6 +643,24 @@
 		http_client_peer_trigger_request_handler(conn->peer);
 }
 
+void http_client_connection_request_destroyed(
+	struct http_client_connection *conn, struct http_client_request *req)
+{
+	struct istream *payload = conn->incoming_payload;
+
+	i_assert(req->conn == conn);
+	if (conn->pending_request != req)
+		return;
+
+	http_client_connection_debug(conn,
+		"Pending request destroyed prematurely");
+
+	if (payload == NULL)
+		return;
+	i_stream_ref(payload);
+	i_stream_destroy(&payload);
+}
+
 static bool
 http_client_connection_return_response(
 	struct http_client_connection *conn,
--- a/src/lib-http/http-client-private.h	Tue May 30 18:25:50 2017 +0300
+++ b/src/lib-http/http-client-private.h	Wed May 24 19:08:43 2017 +0200
@@ -413,6 +413,8 @@
 void http_client_connection_close(struct http_client_connection **_conn);
 
 void http_client_connection_peer_closed(struct http_client_connection **_conn);
+void http_client_connection_request_destroyed(
+	struct http_client_connection *conn, struct http_client_request *req);
 
 int http_client_connection_output(struct http_client_connection *conn);
 void http_client_connection_start_request_timeout(
--- a/src/lib-http/http-client-request.c	Tue May 30 18:25:50 2017 +0300
+++ b/src/lib-http/http-client-request.c	Wed May 24 19:08:43 2017 +0200
@@ -299,6 +299,10 @@
 		req->destroy_callback = NULL;
 		callback(req->destroy_context);
 	}
+
+	if (req->conn != NULL)
+		http_client_connection_request_destroyed(req->conn, req);
+
 	http_client_request_remove(req);
 	http_client_request_unref(&req);
 }