]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Fix segfault occurring when an idle host times out.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 29 Jan 2019 21:16:26 +0000 (22:16 +0100)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Mon, 29 Apr 2019 11:04:32 +0000 (13:04 +0200)
This is most visible when the host is associated with an invalid host name: in
that case the idle timeout is only 100ms. For valid hosts, this problem can only
appear after 30 minutes idle time (default).

Problem is caused by the session host object starting a new idle timeout in the
shared host, while the shared and session host objects are both being destroyed.

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

index 3fc7cd51cbfa6b5f5332e6c235a2ce3cb8894268..701558e4f5cff005765852a48771ef8bbeca1e09 100644 (file)
@@ -24,6 +24,7 @@ http_client_host_lookup_failure(struct http_client_host *host,
        const char *error);
 static bool
 http_client_host_is_idle(struct http_client_host *host);
+static void http_client_host_free_shared(struct http_client_host **_host);
 
 /*
  * Host (shared)
@@ -281,7 +282,7 @@ void http_client_host_shared_free(struct http_client_host_shared **_hshared)
        /* drop client sessions */
        while (hshared->hosts_list != NULL) {
                host = hshared->hosts_list;
-               http_client_host_free(&host);
+               http_client_host_free_shared(&host);
        }
 
        event_unref(&hshared->event);
@@ -347,8 +348,7 @@ http_client_host_get(struct http_client *client,
        return host;
 }
 
-void http_client_host_free(
-       struct http_client_host **_host)
+static void http_client_host_free_shared(struct http_client_host **_host)
 {
        struct http_client_host *host = *_host;
        struct http_client *client = host->client;
@@ -356,6 +356,8 @@ void http_client_host_free(
        struct http_client_queue *const *queue_idx;
        ARRAY_TYPE(http_client_queue) queues;
 
+       *_host = NULL;
+
        e_debug(hshared->event, "Host session destroy");
 
        DLLIST_REMOVE_FULL(&hshared->hosts_list,
@@ -374,9 +376,16 @@ void http_client_host_free(
        array_free(&host->queues);
 
        i_free(host);
+}
+
+void http_client_host_free(struct http_client_host **_host)
+{
+       struct http_client_host *host = *_host;
+       struct http_client_host_shared *hshared = host->shared;
+
+       http_client_host_free_shared(_host);
 
        http_client_host_shared_check_idle(hshared);
-       *_host = NULL;
 }
 
 static void