From: Stephan Bosch Date: Fri, 13 Mar 2020 22:55:50 +0000 (+0100) Subject: lib-http: http-server-request - Add http_server_request_immune_ref/unref() and use... X-Git-Tag: 2.3.11.2~259 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1741c8538070ae45cbc0d4a420018f8f02270567;p=thirdparty%2Fdovecot%2Fcore.git lib-http: http-server-request - Add http_server_request_immune_ref/unref() and use the new API. 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. --- diff --git a/src/lib-http/http-server-connection.c b/src/lib-http/http-server-connection.c index 8be697cedf..d9143b9156 100644 --- a/src/lib-http/http-server-connection.c +++ b/src/lib-http/http-server-connection.c @@ -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 */ diff --git a/src/lib-http/http-server-private.h b/src/lib-http/http-server-private.h index 135c1d67d9..ca09bc48e3 100644 --- a/src/lib-http/http-server-private.h +++ b/src/lib-http/http-server-private.h @@ -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); diff --git a/src/lib-http/http-server-request.c b/src/lib-http/http-server-request.c index ce3c234c83..90241b58f1 100644 --- a/src/lib-http/http-server-request.c +++ b/src/lib-http/http-server-request.c @@ -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) {