changeset 22223:7fa4ccc9a738

push-notification: Switch to main ioloop while calling drivers' commit callbacks There aren't any guarantees what ioloop happens to be active at the time the commit is called. The active ioloop can also be destroyed early on, which can cause an I/O leak and crashes later on.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 12 Jun 2017 23:45:05 +0300
parents 03534f251ebb
children dc1996f95c89
files src/plugins/push-notification/push-notification-plugin.c
diffstat 1 files changed, 10 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/push-notification/push-notification-plugin.c	Fri Jun 09 18:10:14 2017 +0300
+++ b/src/plugins/push-notification/push-notification-plugin.c	Mon Jun 12 23:45:05 2017 +0300
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
+#include "ioloop.h"
 #include "mail-namespace.h"
 #include "mail-storage.h"
 #include "mail-storage-private.h"
@@ -24,7 +25,7 @@
         MODULE_CONTEXT(obj, push_notification_user_module)
 static MODULE_CONTEXT_DEFINE_INIT(push_notification_user_module,
                                   &mail_user_module_register);
-
+static struct ioloop *main_ioloop;
 
 static void
 push_notification_transaction_init(struct push_notification_txn *ptxn)
@@ -102,7 +103,12 @@
 (void *txn, struct mail_transaction_commit_changes *changes)
 {
     struct push_notification_txn *ptxn = (struct push_notification_txn *)txn;
+    struct ioloop *prev_ioloop = current_ioloop;
 
+    /* Make sure we're not in just any random ioloop, which could get
+       destroyed soon. This way the push-notification drivers can do async
+       operations that finish in the main ioloop. */
+    io_loop_set_current(main_ioloop);
     if (changes == NULL) {
         push_notification_txn_mbox_end(ptxn);
     } else {
@@ -110,6 +116,7 @@
     }
 
     push_notification_transaction_end(ptxn, TRUE);
+    io_loop_set_current(prev_ioloop);
 }
 
 static void push_notification_mailbox_create(struct mailbox *box)
@@ -337,6 +344,8 @@
     push_notification_driver_register(&push_notification_driver_ox);
 
     push_notification_event_register_rfc5423_events();
+    main_ioloop = current_ioloop;
+    i_assert(main_ioloop != NULL);
 }
 
 void push_notification_plugin_deinit(void)