From: Stephan Bosch Date: Thu, 21 Feb 2019 01:34:54 +0000 (+0100) Subject: lib: lib-signals - Implement lib_signals_set_expected(). X-Git-Tag: 2.3.13~658 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d39b532db53a258413f0628fbea4ade92ffc03bc;p=thirdparty%2Fdovecot%2Fcore.git lib: lib-signals - Implement lib_signals_set_expected(). This is a promise that the indicated delayed signal will occur eventually, so that the associated ioloop will eventually terminate. This allows the lib-signal io to be alone on the ioloop. --- diff --git a/src/lib/lib-signals.c b/src/lib/lib-signals.c index 359e62fe53..f116052956 100644 --- a/src/lib/lib-signals.c +++ b/src/lib/lib-signals.c @@ -29,6 +29,7 @@ struct signal_handler { struct signal_handler *next; struct ioloop *current_ioloop; + bool expected:1; bool shadowed:1; }; @@ -41,6 +42,7 @@ static struct signal_handler *signal_handlers[MAX_SIGNAL_VALUE+1] = { NULL, }; static int sig_pipe_fd[2] = { -1, -1 }; static bool signals_initialized = FALSE; +static unsigned int signals_expected = 0; static struct io *io_sig = NULL; static siginfo_t pending_signals[MAX_SIGNAL_VALUE+1]; @@ -299,12 +301,24 @@ static void ATTR_NULL(1) signal_read(void *context ATTR_UNUSED) } } +static void lib_signals_update_expected_signals(bool expected) +{ + if (expected) + signals_expected++; + else { + i_assert(signals_expected > 0); + signals_expected--; + } + if (io_sig != NULL) + io_set_never_wait_alone(io_sig, signals_expected == 0); +} + static void lib_signals_enable_delayed_hander(void) { if (current_ioloop != NULL && sig_pipe_fd[0] > 0) { io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL); - io_set_never_wait_alone(io_sig, TRUE); + io_set_never_wait_alone(io_sig, signals_expected == 0); } } @@ -462,6 +476,8 @@ void lib_signals_clear_handlers(int signo) while (h != NULL) { struct signal_handler *h_next = h->next; + if (h->expected) + signals_expected--; i_free(h); h = h_next; } @@ -481,6 +497,8 @@ void lib_signals_unset_handler(int signo, signal_handler_t *handler, } h = *p; *p = h->next; + if (h->expected) + lib_signals_update_expected_signals(FALSE); i_free(h); return; } @@ -490,6 +508,25 @@ void lib_signals_unset_handler(int signo, signal_handler_t *handler, signo, (void *)handler, context); } +void lib_signals_set_expected(int signo, bool expected, + signal_handler_t *handler, void *context) +{ + struct signal_handler *h; + + for (signo = 0; signo < MAX_SIGNAL_VALUE; signo++) { + for (h = signal_handlers[signo]; h != NULL; h = h->next) { + if (h->expected == expected) + return; + h->expected = expected; + lib_signals_update_expected_signals(expected); + return; + } + } + + i_panic("lib_signals_set_expected(%d, %p, %p): handler not found", + signo, (void *)handler, context); +} + void lib_signals_switch_ioloop(int signo, signal_handler_t *handler, void *context) { @@ -556,6 +593,7 @@ void lib_signals_deinit(void) if (signal_handlers[i] != NULL) lib_signals_clear_handlers(i); } + i_assert(signals_expected == 0); lib_signals_ioloop_detach(); diff --git a/src/lib/lib-signals.h b/src/lib/lib-signals.h index a03bd4015c..874cc5aed0 100644 --- a/src/lib/lib-signals.h +++ b/src/lib/lib-signals.h @@ -48,6 +48,13 @@ void lib_signals_unset_handler(int signo, signal_handler_t *handler, void *context) ATTR_NULL(3); +/* Indicate whether signals are expected for the indicated delayed handler. When + signals are expected, the io for delayed handlers will be allowed to wait + alone on the ioloop. */ +void lib_signals_set_expected(int signo, bool expected, + signal_handler_t *handler, void *context); + ATTR_NULL(4); + /* Switch ioloop for a specific signal handler created with LIBSIG_FLAG_NO_IOLOOP_AUTOMOVE. */ void lib_signals_switch_ioloop(int signo,