]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: stats_client_deinit() - Ensure conn.output is flushed before returning
authorMarco Bettini <marco.bettini@open-xchange.com>
Thu, 23 Mar 2023 15:37:28 +0000 (15:37 +0000)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Thu, 24 Aug 2023 08:15:26 +0000 (08:15 +0000)
This prevents losing exported events still waiting in buffers while the process exits.

src/lib-master/stats-client.c

index 6df5d1c39955174577018801cdbfa63253773cc3..1f5037a313f381a05fc4722f12c08658481f54cb 100644 (file)
@@ -301,7 +301,7 @@ static void stats_client_timeout(struct stats_client *client)
        io_loop_stop(client->ioloop);
 }
 
-static void stats_client_wait_handshake(struct stats_client *client)
+static void stats_client_wait(struct stats_client *client)
 {
        struct ioloop *prev_ioloop = current_ioloop;
        struct timeout *to;
@@ -339,7 +339,7 @@ static void stats_client_connect(struct stats_client *client)
                /* read the handshake so the global debug filter is updated */
                stats_client_send_registered_categories(client);
                if (!client->handshake_received_at_least_once)
-                       stats_client_wait_handshake(client);
+                       stats_client_wait(client);
        } else if (!client->silent_notfound_errors ||
                   (errno != ENOENT && errno != ECONNREFUSED)) {
                i_error("net_connect_unix(%s) failed: %m", client->conn.name);
@@ -361,12 +361,34 @@ stats_client_init(const char *path, bool silent_notfound_errors)
        return client;
 }
 
+static int stats_client_deinit_callback(struct connection *conn)
+{
+       struct ostream *output = conn->output;
+       int ret = o_stream_flush(output);
+       if (ret < 0) {
+               e_error(conn->event, "write() failed: %s",
+                       o_stream_get_error(output));
+       }
+       if (ret != 0)
+               io_loop_stop(current_ioloop);
+       return ret;
+}
+
 void stats_client_deinit(struct stats_client **_client)
 {
        struct stats_client *client = *_client;
 
        *_client = NULL;
 
+       if (client->conn.output != NULL && !client->conn.output->closed &&
+           o_stream_get_buffer_used_size(client->conn.output) > 0) {
+               o_stream_set_flush_callback(client->conn.output,
+                                           stats_client_deinit_callback,
+                                           &client->conn);
+               o_stream_uncork(client->conn.output);
+               stats_client_wait(client);
+       }
+
        event_filter_unref(&client->filter);
        connection_deinit(&client->conn);
        timeout_remove(&client->to_reconnect);