]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: When a request is destroyed prematurely during payload input, consi...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Wed, 24 May 2017 19:59:32 +0000 (21:59 +0200)
committerGitLab <gitlab@git.dovecot.net>
Fri, 26 May 2017 09:26:45 +0000 (12:26 +0300)
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.

src/lib-http/http-client-connection.c

index f8f6391676648d3b58dc8c1c9117ea501a9f6ca7..89ee354f80e89517c5cfd9f288c2268ac6d3970d 100644 (file)
@@ -646,7 +646,7 @@ static void http_client_payload_destroyed(struct http_client_request *req)
 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 @@ void http_client_connection_request_destroyed(
        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