]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: http-server-request - Add http_server_request_immune_ref/unref() and use...
authorStephan Bosch <stephan.bosch@open-xchange.com>
Fri, 13 Mar 2020 22:55:50 +0000 (23:55 +0100)
committermartti.rannanjarvi <martti.rannanjarvi@open-xchange.com>
Sat, 18 Apr 2020 14:55:11 +0000 (14:55 +0000)
Makes the request immune to http_server_request_destroy() until the last immune
reference is dropped. The destruction is only delayed, so destroy is implicit
once the last immune reference is dropped.

src/lib-http/http-server-connection.c
src/lib-http/http-server-private.h
src/lib-http/http-server-request.c

index 8be697cedf4c41c151c36c974e249dccb6cb9514..d9143b91564bd46dcd30d53cb0694216a5a29961 100644 (file)
@@ -598,29 +598,20 @@ static void http_server_connection_input(struct connection *_conn)
                                conn->request_queue_count,
                                conn->server->set.max_pipelined_requests);
 
-                       http_server_request_ref(req);
-                       i_assert(!req->delay_destroy);
-                       req->delay_destroy = TRUE;
+                       http_server_request_immune_ref(req);
                        T_BEGIN {
                                cont = http_server_connection_handle_request(conn, req);
                        } T_END;
-                       req->delay_destroy = FALSE;
                        if (!cont) {
                                /* Connection closed or request body not read
                                   yet. The request may be destroyed now. */
-                               if (req->destroy_pending)
-                                       http_server_request_destroy(&req);
-                               else
-                                       http_server_request_unref(&req);
+                               http_server_request_immune_unref(&req);
                                http_server_connection_unref(&conn);
                                return;
                        }
                        if (req->req.connection_close)
                                conn->close_indicated = TRUE;
-                       if (req->destroy_pending)
-                               http_server_request_destroy(&req);
-                       else
-                               http_server_request_unref(&req);
+                       http_server_request_immune_unref(&req);
 
                        if (conn->closed) {
                                /* Connection got closed in destroy callback */
index 135c1d67d93f81e1a404c64527fc9727ed95305f..ca09bc48e32e1ed8a82ed087994688a43d8fe4e7 100644 (file)
@@ -98,7 +98,7 @@ struct http_server_response {
 struct http_server_request {
        struct http_request req;
        pool_t pool;
-       unsigned int refcount;
+       unsigned int refcount, immune_refcount;
        unsigned int id;
        int callback_refcount;
        struct event *event;
@@ -119,7 +119,6 @@ struct http_server_request {
 
        bool payload_halted:1;
        bool sent_100_continue:1;
-       bool delay_destroy:1;
        bool destroy_pending:1;
        bool failed:1;
        bool connection_close:1;
@@ -236,6 +235,9 @@ void http_server_request_destroy(struct http_server_request **_req);
 void http_server_request_abort(struct http_server_request **_req,
                               const char *reason) ATTR_NULL(2);
 
+void http_server_request_immune_ref(struct http_server_request *req);
+void http_server_request_immune_unref(struct http_server_request **_req);
+
 bool http_server_request_is_complete(struct http_server_request *req);
 
 void http_server_request_callback(struct http_server_request *req);
index ce3c234c8331693a3cd46aca96ac3ca9dc3b610a..90241b58f1130b62d6a6a45ee4802a9f844cf04d 100644 (file)
@@ -133,7 +133,7 @@ void http_server_request_destroy(struct http_server_request **_req)
        if (server->ioloop != NULL)
                io_loop_stop(server->ioloop);
 
-       if (req->delay_destroy) {
+       if (req->immune_refcount > 0) {
                req->destroy_pending = TRUE;
                http_server_request_unref(_req);
                return;
@@ -211,6 +211,25 @@ void http_server_request_abort(struct http_server_request **_req,
        http_server_request_destroy(_req);
 }
 
+void http_server_request_immune_ref(struct http_server_request *req)
+{
+       http_server_request_ref(req);
+       req->immune_refcount++;
+}
+
+void http_server_request_immune_unref(struct http_server_request **_req)
+{
+       struct http_server_request *req = *_req;
+
+       i_assert(req->immune_refcount > 0);
+
+       *_req = NULL;
+       if (--req->immune_refcount == 0 && req->destroy_pending)
+               http_server_request_destroy(&req);
+       else
+               http_server_request_unref(&req);
+}
+
 const struct http_request *
 http_server_request_get(struct http_server_request *req)
 {