From: Stephan Bosch Date: Fri, 17 Mar 2017 22:35:55 +0000 (+0100) Subject: lib-http: client: Restructured the handling of delayed errors. X-Git-Tag: 2.2.29.rc1~117 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7b846290fb429af258c0082384f30b1eb70a4828;p=thirdparty%2Fdovecot%2Fcore.git lib-http: client: Restructured the handling of delayed errors. The req->delayed_error* fields are cleared before the callback is called and before the request is dereferenced. This way, freeing the request never removes it from the delayed request list when the list is being processed. It also makes it possible to resubmit the request from the callback (mainly for future use). --- diff --git a/src/lib-http/http-client-request.c b/src/lib-http/http-client-request.c index e6d7449c45..13cdb450e0 100644 --- a/src/lib-http/http-client-request.c +++ b/src/lib-http/http-client-request.c @@ -1197,15 +1197,18 @@ http_client_request_send_error(struct http_client_request *req, void http_client_request_error_delayed(struct http_client_request **_req) { struct http_client_request *req = *_req; + const char *error = req->delayed_error; + unsigned int status = req->delayed_error_status; bool destroy; i_assert(req->state == HTTP_REQUEST_STATE_ABORTED); *_req = NULL; + req->delayed_error = NULL; + req->delayed_error_status = 0; - i_assert(req->delayed_error != NULL && req->delayed_error_status != 0); - destroy = http_client_request_send_error(req, req->delayed_error_status, - req->delayed_error); + i_assert(error != NULL && status != 0); + destroy = http_client_request_send_error(req, status, error); if (req->queue != NULL) http_client_queue_drop_request(req->queue, req); if (destroy) @@ -1219,6 +1222,7 @@ void http_client_request_error(struct http_client_request **_req, *_req = NULL; + i_assert(req->delayed_error_status == 0); i_assert(req->state < HTTP_REQUEST_STATE_FINISHED); req->state = HTTP_REQUEST_STATE_ABORTED; @@ -1230,7 +1234,6 @@ void http_client_request_error(struct http_client_request **_req, /* we're still in http_client_request_submit() or in the callback during a retry attempt. delay reporting the error, so the caller doesn't have to handle immediate or nested callbacks. */ - i_assert(req->delayed_error == NULL); req->delayed_error = p_strdup(req->pool, error); req->delayed_error_status = status; http_client_delay_request_error(req->client, req); diff --git a/src/lib-http/http-client.c b/src/lib-http/http-client.c index 243abb04ce..b40ada5462 100644 --- a/src/lib-http/http-client.c +++ b/src/lib-http/http-client.c @@ -316,11 +316,11 @@ int http_client_init_ssl_ctx(struct http_client *client, const char **error_r) static void http_client_handle_request_errors(struct http_client *client) { + struct http_client_request *const *req_idx; + timeout_remove(&client->to_failing_requests); - while (array_count(&client->delayed_failing_requests) > 0) { - struct http_client_request *const *req_idx = - array_idx(&client->delayed_failing_requests, 0); + array_foreach(&client->delayed_failing_requests, req_idx) { struct http_client_request *req = *req_idx; i_assert(req->refcount == 1);