]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-auth-client: auth-master - Implement auth_master_wait()
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 11 Mar 2018 13:49:50 +0000 (14:49 +0100)
committerStephan Bosch <stephan.bosch@open-xchange.com>
Wed, 27 Aug 2025 14:17:02 +0000 (16:17 +0200)
This allows waiting until all submitted requests are finished.

src/lib-auth-client/auth-master.c
src/lib-auth-client/auth-master.h

index 9cb9b2c5fe699557e67acc6b61f37353198bba31..4612416889ed890ce8e6984517ae5bf980ba0cea 100644 (file)
@@ -12,6 +12,7 @@
 #include "str.h"
 #include "strescape.h"
 #include "time-util.h"
+#include "master-service.h"
 
 #include "auth-master-private.h"
 
@@ -122,6 +123,19 @@ auth_master_connection_failure(struct auth_master_connection *conn,
                io_loop_stop(conn->ioloop);
 }
 
+static void
+auth_master_connection_abort_requests(struct auth_master_connection *conn)
+{
+       struct auth_master_request *req;
+
+       while (conn->requests_head != NULL) {
+               req = conn->requests_head;
+
+               auth_master_request_abort(&req);
+       }
+       i_assert(hash_table_count(conn->requests) == 0);
+}
+
 void auth_master_disconnect(struct auth_master_connection *conn)
 {
        connection_disconnect(&conn->conn);
@@ -478,6 +492,72 @@ void auth_master_stop_idle(struct auth_master_connection *conn)
        timeout_remove(&conn->to_idle);
 }
 
+static void auth_master_stop(struct auth_master_connection *conn)
+{
+       if (master_service_is_killed(master_service)) {
+               auth_master_connection_abort_requests(conn);
+               io_loop_stop(conn->ioloop);
+       }
+}
+
+void auth_master_wait(struct auth_master_connection *conn)
+{
+       struct ioloop *ioloop, *prev_ioloop;
+       struct timeout *to;
+       bool waiting = conn->waiting, was_corked = FALSE;
+
+       i_assert(conn->ioloop == NULL);
+       i_assert(auth_master_request_count(conn) > 0);
+
+       auth_master_ref(conn);
+
+       if ((conn->flags & AUTH_MASTER_FLAG_NO_INNER_IOLOOP) != 0)
+               ioloop = conn->ioloop;
+       else {
+               prev_ioloop = conn->ioloop;
+               if (!waiting)
+                       conn->prev_ioloop = prev_ioloop;
+               ioloop = io_loop_create();
+               auth_master_switch_ioloop_to(conn, ioloop);
+       }
+
+       if (conn->conn.input != NULL &&
+           i_stream_get_data_size(conn->conn.input) > 0)
+               i_stream_set_input_pending(conn->conn.input, TRUE);
+       o_stream_set_flush_pending(conn->conn.output, TRUE);
+       if (conn->conn.output != NULL) {
+               was_corked = o_stream_is_corked(conn->conn.output);
+               o_stream_uncork(conn->conn.output);
+       }
+
+       /* either we're waiting for network I/O or we're getting out of a
+          callback using timeout_add_short(0) */
+       i_assert(io_loop_have_ios(ioloop) ||
+                io_loop_have_immediate_timeouts(ioloop));
+
+       /* add stop handler */
+       to = timeout_add_short(100, auth_master_stop, conn);
+
+       conn->waiting = TRUE;
+       while (auth_master_request_count(conn) > 0)
+               io_loop_run(ioloop);
+       conn->waiting = waiting;
+
+       timeout_remove(&to);
+
+       if (conn->conn.output != NULL && was_corked)
+               o_stream_cork(conn->conn.output);
+
+       if ((conn->flags & AUTH_MASTER_FLAG_NO_INNER_IOLOOP) == 0) {
+               auth_master_switch_ioloop_to(conn, prev_ioloop);
+               io_loop_destroy(&ioloop);
+               if (!waiting)
+                       conn->prev_ioloop = NULL;
+       }
+
+       auth_master_unref(&conn);
+}
+
 /*
  * Lookup common
  */
index bf7b93f76b848b4280b70acb8699b1c8eb66329b..693f0ebf991f5683556971250aa1d8cb5366105d 100644 (file)
@@ -75,6 +75,7 @@ const char *auth_master_get_socket_path(struct auth_master_connection *conn);
 void auth_master_switch_ioloop_to(struct auth_master_connection *conn,
                                  struct ioloop *ioloop);
 void auth_master_switch_ioloop(struct auth_master_connection *conn);
+void auth_master_wait(struct auth_master_connection *conn);
 
 /*
  * Lookup common