lib-signals.c revision 40377343c4f73dba03d4294fc76eec05276403ec
/* Copyright (c) 2001-2003 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "fd-close-on-exec.h"
#include "lib-signals.h"
#include <signal.h>
#include <unistd.h>
#define MAX_SIGNAL_VALUE 31
struct signal_handler {
void *context;
bool delayed;
struct signal_handler *next;
};
/* Remember that these are accessed inside signal handler which may be called
even while we're initializing/deinitializing. Try hard to keep everything
in consistent state. */
static int sig_pipe_fd[2];
static void sig_handler(int signo)
{
struct signal_handler *h;
bool delayed_sent = FALSE;
return;
/* remember that we're inside a signal handler which might have been
called at any time. don't do anything that's unsafe. */
if (!h->delayed)
else if (!delayed_sent) {
int saved_errno = errno;
unsigned char signo_byte = signo;
i_error("write(sigpipe) failed: %m");
delayed_sent = TRUE;
errno = saved_errno;
}
}
}
{
/* if we used SIG_IGN instead of this function,
the system call might be restarted */
}
{
unsigned char signal_buf[512];
int signo;
if (ret > 0) {
/* move them to mask first to avoid calling same handler
multiple times */
for (i = 0; i < ret; i++) {
signo = signal_buf[i];
if (signo > MAX_SIGNAL_VALUE) {
i_panic("sigpipe contains signal %d > %d",
}
}
/* call the delayed handlers */
if (signal_mask[signo] > 0) {
struct signal_handler *h =
if (h->delayed)
}
}
}
} else if (ret < 0) {
i_fatal("read(sigpipe) failed: %m");
} else {
i_fatal("read(sigpipe) failed: EOF");
}
}
{
struct signal_handler *h;
i_panic("Trying to set signal %d handler, but max is %d",
}
/* first handler for this signal */
i_fatal("sigemptyset(): %m");
/* we're ignoring the handler, just return */
return;
}
}
/* first delayed handler */
if (pipe(sig_pipe_fd) < 0)
i_fatal("pipe() failed: %m");
}
/* atomically set to signal_handlers[] list */
signal_handlers[signo] = h;
}
void lib_signals_ignore(int signo)
{
i_panic("Trying to ignore signal %d, but max is %d",
}
i_fatal("sigemptyset(): %m");
}
void *context)
{
struct signal_handler *h, **p;
h = *p;
*p = h->next;
i_free(h);
return;
}
}
i_panic("lib_signals_unset_handler(%d, %p, %p): handler not found",
}
void lib_signals_init(void)
{
}
void lib_signals_deinit(void)
{
struct signal_handler *handlers, *h;
int i;
for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
if (signal_handlers[i] != NULL) {
/* atomically remove from signal_handlers[] list */
handlers = signal_handlers[i];
signal_handlers[i] = NULL;
h = handlers;
i_free(h);
}
}
}
if (sig_pipe_fd[0] != -1) {
if (close(sig_pipe_fd[0]) < 0)
i_error("close(sigpipe) failed: %m");
i_error("close(sigpipe) failed: %m");
}
}