]> 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)
committerGitLab <gitlab@git.dovecot.net>
Wed, 22 Mar 2017 18:41:09 +0000 (20:41 +0200)
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 471887f98457519d572ad62c8b7be1aac944ef66..2e38abeec892d3f5d39a39eb83fd77a71e2a0a90 100644 (file)
@@ -1192,15 +1192,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)
@@ -1214,6 +1217,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;
 
@@ -1225,7 +1229,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 b7f71f0095cd393c0c374e51729a758fc355c8c5..6f36c4c5d36e50ac155ca8687af75675a11d4496 100644 (file)
@@ -303,11 +303,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);