lib-signals.c revision 94a1aac0916108152fc97f5cf94e7095ac7fcbbd
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2001-2009 Dovecot authors, see the included COPYING file */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "lib.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "ioloop.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "fd-close-on-exec.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "lib-signals.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen#include <signal.h>
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen#include <unistd.h>
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#define MAX_SIGNAL_VALUE 31
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstruct signal_handler {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen signal_handler_t *handler;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen void *context;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen bool delayed;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct signal_handler *next;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen};
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen/* Remember that these are accessed inside signal handler which may be called
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen even while we're initializing/deinitializing. Try hard to keep everything
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen in consistent state. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic struct signal_handler *signal_handlers[MAX_SIGNAL_VALUE+1] = { NULL, };
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic int sig_pipe_fd[2] = { -1, -1 };
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic bool signals_initialized = FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic struct io *io_sig = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic siginfo_t pending_signals[MAX_SIGNAL_VALUE+1];
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic bool have_pending_signals = FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenconst char *lib_signal_code_to_str(int signo, int sicode)
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* common */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen switch (sicode) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#ifdef SI_NOINFO
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case SI_NOINFO:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#endif
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case SI_USER:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "kill";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#ifdef SI_KERNEL
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case SI_KERNEL:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "kernel";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#endif
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen case SI_TIMER:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "timer";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
2200adee458ca662d32b5ec0e01d8c5cba0cc0a8Timo Sirainen /* If SEGV_MAPERR is supported, the rest of them must be too.
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen FreeBSD 6 at least doesn't support these. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#ifdef SEGV_MAPERR
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen switch (signo) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case SIGSEGV:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen switch (sicode) {
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen case SEGV_MAPERR:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "address not mapped";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case SEGV_ACCERR:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "invalid permissions";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case SIGBUS:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen switch (sicode) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case BUS_ADRALN:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "invalid address alignment";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case BUS_ADRERR:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "nonexistent physical address";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case BUS_OBJERR:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "object-specific hardware error";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#endif
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return t_strdup_printf("unknown %d", sicode);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic void sig_handler(int signo, siginfo_t *si, void *context ATTR_UNUSED)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct signal_handler *h;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen char c = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#ifdef SI_NOINFO
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen siginfo_t tmp_si;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (si == NULL) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* Solaris can leave this to NULL */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen memset(&tmp_si, 0, sizeof(tmp_si));
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen tmp_si.si_signo = signo;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen tmp_si.si_code = SI_NOINFO;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen si = &tmp_si;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#endif
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (signo < 0 || signo > MAX_SIGNAL_VALUE)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* remember that we're inside a signal handler which might have been
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen called at any time. don't do anything that's unsafe. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (h = signal_handlers[signo]; h != NULL; h = h->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (!h->delayed)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen h->handler(si, h->context);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen else if (pending_signals[signo].si_signo == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen pending_signals[signo] = *si;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (!have_pending_signals) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen int saved_errno = errno;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (write(sig_pipe_fd[1], &c, 1) != 1)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_error("write(sigpipe) failed: %m");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen have_pending_signals = TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen errno = saved_errno;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainenstatic void sig_ignore(int signo ATTR_UNUSED, siginfo_t *si ATTR_UNUSED,
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen void *context ATTR_UNUSED)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* if we used SIG_IGN instead of this function,
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen the system call might be restarted */
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen}
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainenstatic void signal_read(void *context ATTR_UNUSED)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen{
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen siginfo_t signals[MAX_SIGNAL_VALUE+1];
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen sigset_t fullset, oldset;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen struct signal_handler *h;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen char buf[2];
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen int signo;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen ssize_t ret;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (sigfillset(&fullset) < 0)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_fatal("sigfillset() failed: %m");
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (sigprocmask(SIG_BLOCK, &fullset, &oldset) < 0)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_fatal("sigprocmask() failed: %m");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen ret = read(sig_pipe_fd[0], buf, sizeof(buf));
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(ret <= 1);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (ret > 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen memcpy(signals, pending_signals, sizeof(signals));
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen memset(pending_signals, 0, sizeof(pending_signals));
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen have_pending_signals = FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } else if (ret < 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (errno != EAGAIN)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_fatal("read(sigpipe) failed: %m");
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen } else {
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen i_fatal("read(sigpipe) failed: EOF");
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen }
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0)
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen i_fatal("sigprocmask() failed: %m");
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen if (ret < 0)
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen return;
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen /* call the delayed handlers after signals are copied and unblocked */
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen for (signo = 0; signo < MAX_SIGNAL_VALUE; signo++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (signals[signo].si_signo == 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen continue;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (h = signal_handlers[signo]; h != NULL; h = h->next) {
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (h->delayed)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen h->handler(&signals[signo], h->context);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic void lib_signals_set(int signo, bool ignore)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct sigaction act;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (sigemptyset(&act.sa_mask) < 0)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_fatal("sigemptyset(): %m");
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen act.sa_flags = SA_SIGINFO;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen act.sa_sigaction = ignore ? sig_ignore : sig_handler;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (sigaction(signo, &act, NULL) < 0)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_fatal("sigaction(%d): %m", signo);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen}
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainenvoid lib_signals_set_handler(int signo, bool delayed,
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen signal_handler_t *handler, void *context)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen{
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen struct signal_handler *h;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_assert(handler != NULL);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (signo < 0 || signo > MAX_SIGNAL_VALUE) {
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_panic("Trying to set signal %d handler, but max is %d",
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen signo, MAX_SIGNAL_VALUE);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen }
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (signal_handlers[signo] == NULL && signals_initialized)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen lib_signals_set(signo, FALSE);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (delayed && sig_pipe_fd[0] == -1) {
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen /* first delayed handler */
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (pipe(sig_pipe_fd) < 0)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_fatal("pipe() failed: %m");
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen fd_close_on_exec(sig_pipe_fd[0], TRUE);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen fd_close_on_exec(sig_pipe_fd[1], TRUE);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (signals_initialized) {
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen io_sig = io_add(sig_pipe_fd[0], IO_READ,
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen signal_read, NULL);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen }
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen }
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen h = i_new(struct signal_handler, 1);
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen h->handler = handler;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen h->context = context;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen h->delayed = delayed;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen /* atomically set to signal_handlers[] list */
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen h->next = signal_handlers[signo];
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen signal_handlers[signo] = h;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen}
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_ignore(int signo, bool restart_syscalls)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct sigaction act;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (signo < 0 || signo > MAX_SIGNAL_VALUE) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_panic("Trying to ignore signal %d, but max is %d",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen signo, MAX_SIGNAL_VALUE);
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen }
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen i_assert(signal_handlers[signo] == NULL);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (sigemptyset(&act.sa_mask) < 0)
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen i_fatal("sigemptyset(): %m");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (restart_syscalls) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen act.sa_flags = SA_RESTART;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen act.sa_handler = SIG_IGN;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } else {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen act.sa_flags = SA_SIGINFO;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen act.sa_sigaction = sig_ignore;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (sigaction(signo, &act, NULL) < 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_fatal("sigaction(%d): %m", signo);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_unset_handler(int signo, signal_handler_t *handler,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen void *context)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen struct signal_handler *h, **p;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (p = &signal_handlers[signo]; *p != NULL; p = &(*p)->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((*p)->handler == handler && (*p)->context == context) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen h = *p;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *p = h->next;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_free(h);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_panic("lib_signals_unset_handler(%d, %p, %p): handler not found",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen signo, (void *)handler, context);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_reset_ioloop(void)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (io_sig != NULL) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen io_remove(&io_sig);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_init(void)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen int i;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen signals_initialized = TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* add signals that were already registered */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (signal_handlers[i] != NULL)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen lib_signals_set(i, FALSE);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (sig_pipe_fd[0] != -1)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_deinit(void)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct signal_handler *handlers, *h;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen int i;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (signal_handlers[i] != NULL) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* atomically remove from signal_handlers[] list */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen handlers = signal_handlers[i];
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen signal_handlers[i] = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen while (handlers != NULL) {
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen h = handlers;
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen handlers = h->next;
1c3dc4c08ced3948f52c3c6c171ed77310b2cbfdTimo Sirainen i_free(h);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (io_sig != NULL)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen io_remove(&io_sig);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (sig_pipe_fd[0] != -1) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (close(sig_pipe_fd[0]) < 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_error("close(sigpipe) failed: %m");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (close(sig_pipe_fd[1]) < 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_error("close(sigpipe) failed: %m");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen