From: Timo Sirainen Date: Thu, 14 Apr 2022 15:19:19 +0000 (+0200) Subject: lib-master: Wait for initial status notification write to finish before continuing X-Git-Tag: 2.4.0~4084 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=987db0b9ff9ef375173ee9bf24a24fb2b5806ba6;p=thirdparty%2Fdovecot%2Fcore.git lib-master: Wait for initial status notification write to finish before continuing 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. --- diff --git a/src/lib-master/master-service-private.h b/src/lib-master/master-service-private.h index 759d25a029..de7296c85b 100644 --- a/src/lib-master/master-service-private.h +++ b/src/lib-master/master-service-private.h @@ -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); diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index e094aad222..230ebcddf8 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -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)