]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: Wait for initial status notification write to finish before continuing
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 14 Apr 2022 15:19:19 +0000 (17:19 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 4 May 2022 05:44:00 +0000 (05:44 +0000)
Otherwise if the process dies early, master might think the service is
broken and start throttling it. This would only happen if the initial
write() failed with EAGAIN, meaning master was very busy and didn't have
time to read all the notification pipes.

src/lib-master/master-service-private.h
src/lib-master/master-service.c

index 759d25a02944f273b48685ad69f0f18f3a52d08b..de7296c85bd99a5a48164337cd7995e4b091ae9d 100644 (file)
@@ -98,6 +98,7 @@ struct master_service {
        bool log_initialized:1;
        bool init_finished:1;
        bool killed_signal_logged:1;
+       bool io_status_waiting:1;
 };
 
 void master_service_io_listeners_add(struct master_service *service);
index e094aad22232588ac39e46f77469a5582145aa01..230ebcddf8eea95db7046f97ce3104f43dfdd4a1 100644 (file)
@@ -868,6 +868,17 @@ static void master_status_error(struct master_service *service)
        master_service_error(service);
 }
 
+static void master_status_update_wait(struct master_service *service)
+{
+       struct ioloop *ioloop = io_loop_create();
+       service->io_status_waiting = TRUE;
+       service->io_status_write = io_loop_move_io(&service->io_status_write);
+       while (service->io_status_write != NULL)
+               io_loop_run(ioloop);
+       service->io_status_waiting = FALSE;
+       io_loop_destroy(&ioloop);
+}
+
 void master_service_init_finish(struct master_service *service)
 {
        struct stat st;
@@ -921,6 +932,8 @@ void master_service_init_finish(struct master_service *service)
                service->master_status.available_count--;
        }
        master_status_update(service);
+       if (service->io_status_write != NULL)
+               master_status_update_wait(service);
 
        /* close data stack frame opened by master_service_init() */
        if ((service->flags & MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME) == 0) {
@@ -1809,6 +1822,13 @@ master_status_send(struct master_service *service, bool important_update)
                                       master_status_update, service);
                }
        }
+       if (service->io_status_waiting &&
+           service->io_status_write == NULL) {
+               /* Waiting in an inner ioloop in master_status_update_wait()
+                  for the status write to finish (succeed or permanently
+                  fail) */
+               io_loop_stop(current_ioloop);
+       }
 }
 
 void master_status_update(struct master_service *service)