]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Restructured the handling of delayed errors.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 17 Mar 2017 22:35:55 +0000 (23:35 +0100)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 27 Mar 2017 09:43:25 +0000 (12:43 +0300)
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).

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

index e6d7449c4524444c69405e46b161c3508f25b327..13cdb450e0d7b8fbe0a835ee4bba7e4b12b4d63b 100644 (file)
@@ -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);
index 243abb04cea1bacd642f433ec708e1043b90781d..b40ada546226a65b57573d5e6d1b3ce0961bae3f 100644 (file)
@@ -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);