lib-signals.c revision 94a1aac0916108152fc97f5cf94e7095ac7fcbbd
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2001-2009 Dovecot authors, see the included COPYING file */
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 siginfo_t pending_signals[MAX_SIGNAL_VALUE+1];
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenconst char *lib_signal_code_to_str(int signo, int sicode)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "kill";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "kernel";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "timer";
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 return "address not mapped";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "invalid permissions";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "invalid address alignment";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "nonexistent physical address";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return "object-specific hardware error";
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic void sig_handler(int signo, siginfo_t *si, void *context ATTR_UNUSED)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* Solaris can leave this to NULL */
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 else if (pending_signals[signo].si_signo == 0) {
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainenstatic void sig_ignore(int signo ATTR_UNUSED, siginfo_t *si ATTR_UNUSED,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* if we used SIG_IGN instead of this function,
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen the system call might be restarted */
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainenstatic void signal_read(void *context ATTR_UNUSED)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (sigprocmask(SIG_BLOCK, &fullset, &oldset) < 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen memcpy(signals, pending_signals, sizeof(signals));
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen memset(pending_signals, 0, sizeof(pending_signals));
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } else if (ret < 0) {
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0)
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen /* call the delayed handlers after signals are copied and unblocked */
8c3872c26b18421d62c52cbfe0b81b1d79239f89Timo Sirainen for (signo = 0; signo < MAX_SIGNAL_VALUE; signo++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (h = signal_handlers[signo]; h != NULL; h = h->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic void lib_signals_set(int signo, bool ignore)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen act.sa_sigaction = ignore ? sig_ignore : sig_handler;
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainenvoid lib_signals_set_handler(int signo, bool delayed,
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen i_panic("Trying to set signal %d handler, but max is %d",
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen if (signal_handlers[signo] == NULL && signals_initialized)
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen /* first delayed handler */
31fd39a3a3d544b1a8afb9aef07f180d0d40fda2Timo Sirainen /* atomically set to signal_handlers[] list */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_ignore(int signo, bool restart_syscalls)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_panic("Trying to ignore signal %d, but max is %d",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_unset_handler(int signo, signal_handler_t *handler,
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen struct signal_handler *h, **p;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (p = &signal_handlers[signo]; *p != NULL; p = &(*p)->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((*p)->handler == handler && (*p)->context == context) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_panic("lib_signals_unset_handler(%d, %p, %p): handler not found",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* add signals that were already registered */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* atomically remove from signal_handlers[] list */