]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: io_loop_context_new() no longer implicitly activates the context
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 3 Feb 2021 18:42:50 +0000 (20:42 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 24 Feb 2021 17:19:49 +0000 (17:19 +0000)
The new behavior requires explicitly activating the context. This change
was needed, because an implicit creation activated the context but didn't
call any of the callbacks. If ioloop wasn't run, the activation callbacks
were never called. This meant that when context was deactivated, the
deactivation callbacks weren't run either.

src/imap-hibernate/imap-client.c
src/lib-storage/mail-storage-service.c
src/lib/ioloop.c
src/lib/ioloop.h

index 358030f887f7aeb8ead0ca927a2fb22e05c8c5e5..d62a346beb821cf4d1d1a1544266d1f3bdc94751 100644 (file)
@@ -730,7 +730,7 @@ void imap_client_create_finish(struct imap_client *client)
        io_loop_context_add_callbacks(client->ioloop_ctx,
                                      imap_client_io_activate_user,
                                      imap_client_io_deactivate_user, client);
-       imap_client_io_activate_user(client);
+       io_loop_context_switch(client->ioloop_ctx);
 
        if (client->state.idle_cmd) {
                client->io = io_add(client->fd, IO_READ,
index 8f96fb1ae7ad8abaa4f0bf0cf6c4e94fbb38839a..e3fdd17af76b86256ffc063ec25069f5f39a1196 100644 (file)
@@ -1526,6 +1526,7 @@ mail_storage_service_next_real(struct mail_storage_service_ctx *ctx,
                                      mail_storage_service_io_deactivate_user_cb,
                                      user);
        }
+       io_loop_context_switch(user->ioloop_ctx);
 
        if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
                if (service_drop_privileges(user, &priv,
index 00b56cb9820e91e6ab28dc0636f307c5c176bdb6..1e854c534e9f0fd9eed40f25483749ef7cdbfd03 100644 (file)
@@ -727,7 +727,7 @@ void io_loop_run(struct ioloop *ioloop)
                io_loop_initialize_handler(ioloop);
 
        if (ioloop->cur_ctx != NULL)
-               io_loop_context_unref(&ioloop->cur_ctx);
+               io_loop_context_deactivate(ioloop->cur_ctx);
 
        /* recursive io_loop_run() isn't allowed for the same ioloop.
           it can break backends. */
@@ -1025,14 +1025,6 @@ struct ioloop_context *io_loop_context_new(struct ioloop *ioloop)
        ctx->refcount = 2;
        ctx->ioloop = ioloop;
        i_array_init(&ctx->callbacks, 4);
-
-       if (ioloop->cur_ctx != NULL) {
-               io_loop_context_deactivate(ioloop->cur_ctx);
-               /* deactivation may remove the cur_ctx */
-               if (ioloop->cur_ctx != NULL)
-                       io_loop_context_unref(&ioloop->cur_ctx);
-       }
-       ioloop->cur_ctx = ctx;
        return ctx;
 }
 
@@ -1150,6 +1142,19 @@ void io_loop_context_deactivate(struct ioloop_context *ctx)
        io_loop_context_unref(&ctx);
 }
 
+void io_loop_context_switch(struct ioloop_context *ctx)
+{
+       if (ctx->ioloop->cur_ctx != NULL) {
+               if (ctx->ioloop->cur_ctx == ctx)
+                       return;
+               io_loop_context_deactivate(ctx->ioloop->cur_ctx);
+               /* deactivation may remove the cur_ctx */
+               if (ctx->ioloop->cur_ctx != NULL)
+                       io_loop_context_unref(&ctx->ioloop->cur_ctx);
+       }
+       io_loop_context_activate(ctx);
+}
+
 struct ioloop_context *io_loop_get_current_context(struct ioloop *ioloop)
 {
        return ioloop->cur_ctx;
index 901686e4fba684cf2d54fd1ead0524568a79a520..75c6ef9f8743b526d60bd1fcd1ec378f62648206 100644 (file)
@@ -215,14 +215,15 @@ void io_loop_remove_switch_callback(io_switch_callback_t *callback);
 void io_loop_add_destroy_callback(io_destroy_callback_t *callback);
 void io_loop_remove_destroy_callback(io_destroy_callback_t *callback);
 
-/* Create a new ioloop context. This context is automatically attached to all
-   the following I/Os and timeouts that are added until the context is
-   deactivated (e.g. returning to back to a running ioloop). Whenever such
-   added I/O or timeout callback is called, this context is automatically
-   activated.
-
-   Creating this context already deactivates any currently running context
-   and activates the newly created context. */
+/* Create a new ioloop context. While the context is activated, it's
+   automatically attached to all the following I/Os and timeouts that are
+   added until the context is deactivated (e.g. returning to back to a running
+   ioloop). Whenever such added I/O or timeout callback is called, this context
+   is automatically activated.
+
+   After the context is created, callbacks should be added to it and the
+   context should be activated with either io_loop_context_activate() or
+   io_loop_context_switch(). */
 struct ioloop_context *io_loop_context_new(struct ioloop *ioloop);
 void io_loop_context_ref(struct ioloop_context *ctx);
 void io_loop_context_unref(struct ioloop_context **ctx);
@@ -266,6 +267,9 @@ void io_loop_context_activate(struct ioloop_context *ctx);
    active or it assert-crashes. This should be called only after a context
    was explicitly activated with io_loop_context_activate(). */
 void io_loop_context_deactivate(struct ioloop_context *ctx);
+/* If there's an active ioloop context, deactivate it. Then activate the given
+   context. Usually used after creating a new context. */
+void io_loop_context_switch(struct ioloop_context *ctx);
 
 /* Returns fd, which contains all of the ioloop's current notifications.
    When it becomes readable, there is a new notification. Calling this function