]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: When clearing signal handlers, ignore the signals instead of restoring defaults
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 6 Aug 2020 14:46:07 +0000 (17:46 +0300)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Mon, 10 Aug 2020 11:16:43 +0000 (11:16 +0000)
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.

src/lib-test/test-subprocess.c
src/lib/lib-signals.c
src/lib/lib-signals.h

index e1bd1d237ae842a5d4c9d6d19842aa37ab6ac160..f7824c93e11f0c2c3efdc238ab99797236d4e67f 100644 (file)
@@ -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();
index 392317554d37f5cb31874a944ab6a5da972965a3..6ac657a045ea0c809f7d6d5cd049b313c43b3be2 100644 (file)
@@ -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);
 
index f73a1fdf7f135f560d3e67dd8e2fd3861914a65a..d491de74c317bb2283b8ec2dc9c1aba2df97a112 100644 (file)
@@ -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)