From: Timo Sirainen Date: Thu, 6 Aug 2020 14:46:07 +0000 (+0300) Subject: lib: When clearing signal handlers, ignore the signals instead of restoring defaults X-Git-Tag: 2.3.13~416 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75693aa152daeee2d81bb8025dbf9bfbbfbca12b;p=thirdparty%2Fdovecot%2Fcore.git lib: When clearing signal handlers, ignore the signals instead of restoring defaults This is mainly happening in while the process is shutting down. Getting a signal at a time when the normal signal handlers are gone isn't something that is expected. It's better to just ignore the signal and let the process to finish shutting down normally instead of getting killed. This should also fix some unit tests where the child processes were sometimes dying with SIGTERM due to these race conditions. --- diff --git a/src/lib-test/test-subprocess.c b/src/lib-test/test-subprocess.c index e1bd1d237a..f7824c93e1 100644 --- a/src/lib-test/test-subprocess.c +++ b/src/lib-test/test-subprocess.c @@ -65,8 +65,7 @@ test_subprocess_child(int (*func)(void *context), void *context, ret = func(context); /* Prevent race condition */ - lib_signals_clear_handlers(SIGTERM); - lib_signals_ignore(SIGTERM, TRUE); + lib_signals_clear_handlers_and_ignore(SIGTERM); event_unref(&test_subprocess_event); lib_signals_deinit(); diff --git a/src/lib/lib-signals.c b/src/lib/lib-signals.c index 392317554d..6ac657a045 100644 --- a/src/lib/lib-signals.c +++ b/src/lib/lib-signals.c @@ -520,17 +520,10 @@ void lib_signals_set_handler(int signo, enum libsig_flags flags, signal_handler_switch_ioloop(h); } -void lib_signals_ignore(int signo, bool restart_syscalls) +static void lib_signals_ignore_forced(int signo, bool restart_syscalls) { struct sigaction act; - if (signo < 0 || signo > MAX_SIGNAL_VALUE) { - i_panic("Trying to ignore signal %d, but max is %d", - signo, MAX_SIGNAL_VALUE); - } - - i_assert(signal_handlers[signo] == NULL); - if (sigemptyset(&act.sa_mask) < 0) i_fatal("sigemptyset(): %m"); if (restart_syscalls) { @@ -550,26 +543,26 @@ void lib_signals_ignore(int signo, bool restart_syscalls) i_fatal("sigaction(%d): %m", signo); } -static void lib_signals_restore_system_default(int signo) +void lib_signals_ignore(int signo, bool restart_syscalls) { - struct sigaction act; + if (signo < 0 || signo > MAX_SIGNAL_VALUE) { + i_panic("Trying to ignore signal %d, but max is %d", + signo, MAX_SIGNAL_VALUE); + } - if (sigemptyset(&act.sa_mask) < 0) - i_fatal("sigemptyset(): %m"); - act.sa_flags = 0; - act.sa_handler = SIG_DFL; - if (sigaction(signo, &act, NULL) < 0) - i_fatal("sigaction(%d): %m", signo); + i_assert(signal_handlers[signo] == NULL); + + lib_signals_ignore_forced(signo, restart_syscalls); } -void lib_signals_clear_handlers(int signo) +void lib_signals_clear_handlers_and_ignore(int signo) { struct signal_handler *h; if (signal_handlers[signo] == NULL) return; - lib_signals_restore_system_default(signo); + lib_signals_ignore_forced(signo, TRUE); h = signal_handlers[signo]; signal_handlers[signo] = NULL; @@ -594,7 +587,7 @@ void lib_signals_unset_handler(int signo, signal_handler_t *handler, if (p == &signal_handlers[signo] && (*p)->next == NULL) { /* last handler is to be removed */ - lib_signals_restore_system_default(signo); + lib_signals_ignore_forced(signo, TRUE); } h = *p; *p = h->next; @@ -691,7 +684,7 @@ void lib_signals_deinit(void) for (i = 0; i < MAX_SIGNAL_VALUE; i++) { if (signal_handlers[i] != NULL) - lib_signals_clear_handlers(i); + lib_signals_clear_handlers_and_ignore(i); } i_assert(signals_expected == 0); diff --git a/src/lib/lib-signals.h b/src/lib/lib-signals.h index f73a1fdf7f..d491de74c3 100644 --- a/src/lib/lib-signals.h +++ b/src/lib/lib-signals.h @@ -42,9 +42,9 @@ void lib_signals_set_handler(int signo, enum libsig_flags flags, ATTR_NULL(4); /* Ignore given signal. */ void lib_signals_ignore(int signo, bool restart_syscalls); -/* Clear all signal handlers for a specific signal and restore default system - handler. */ -void lib_signals_clear_handlers(int signo); +/* Clear all signal handlers for a specific signal and set the signal to be + ignored. */ +void lib_signals_clear_handlers_and_ignore(int signo); /* Unset specific signal handler for specific signal. */ void lib_signals_unset_handler(int signo, signal_handler_t *handler, void *context)