diff options
Diffstat (limited to 'lib/libevent/signal.c')
-rw-r--r-- | lib/libevent/signal.c | 74 |
1 files changed, 58 insertions, 16 deletions
diff --git a/lib/libevent/signal.c b/lib/libevent/signal.c index 2bd98148760..8df05c5d32a 100644 --- a/lib/libevent/signal.c +++ b/lib/libevent/signal.c @@ -1,4 +1,4 @@ -/* $OpenBSD: signal.c,v 1.5 2005/04/19 08:07:45 deraadt Exp $ */ +/* $OpenBSD: signal.c,v 1.6 2005/04/22 00:56:25 brad Exp $ */ /* * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> @@ -37,23 +37,20 @@ #include <sys/_time.h> #endif #include <sys/queue.h> +#include <sys/socket.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> -#include <err.h> - -#ifdef USE_LOG -#include "log.h" -#else -#define LOG_DBG(x) -#define log_error(x) perror(x) +#ifdef HAVE_FCNTL_H +#include <fcntl.h> #endif #include "event.h" #include "evsignal.h" +#include "log.h" extern struct event_list signalqueue; @@ -61,26 +58,63 @@ static short evsigcaught[NSIG]; static int needrecalc; volatile sig_atomic_t evsignal_caught = 0; -void evsignal_process(void); -int evsignal_recalc(sigset_t *); -int evsignal_deliver(sigset_t *); +static struct event ev_signal; +static int ev_signal_pair[2]; +static int ev_signal_added; + +/* Callback for when the signal handler write a byte to our signaling socket */ +static void evsignal_cb(int fd, short what, void *arg) +{ + static char signals[100]; + struct event *ev = arg; + int n; + + n = read(fd, signals, sizeof(signals)); + if (n == -1) + event_err(1, "%s: read", __func__); + event_add(ev, NULL); +} + +#ifdef HAVE_SETFD +#define FD_CLOSEONEXEC(x) do { \ + if (fcntl(x, F_SETFD, 1) == -1) \ + event_warn("fcntl(%d, F_SETFD)", x); \ +} while (0) +#else +#define FD_CLOSEONEXEC(x) +#endif void evsignal_init(sigset_t *evsigmask) { sigemptyset(evsigmask); + + /* + * Our signal handler is going to write to one end of the socket + * pair to wake up our event loop. The event loop then scans for + * signals that got delivered. + */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1) + event_err(1, "%s: socketpair", __func__); + + FD_CLOSEONEXEC(ev_signal_pair[0]); + FD_CLOSEONEXEC(ev_signal_pair[1]); + + event_set(&ev_signal, ev_signal_pair[1], EV_READ, + evsignal_cb, &ev_signal); + ev_signal.ev_flags |= EVLIST_INTERNAL; } int evsignal_add(sigset_t *evsigmask, struct event *ev) { int evsignal; - + if (ev->ev_events & (EV_READ|EV_WRITE)) - errx(1, "%s: EV_SIGNAL incompatible use", __func__); + event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); evsignal = EVENT_SIGNAL(ev); sigaddset(evsigmask, evsignal); - + return (0); } @@ -105,6 +139,9 @@ evsignal_handler(int sig) { evsigcaught[sig]++; evsignal_caught = 1; + + /* Wake up our notification mechanism */ + write(ev_signal_pair[0], "a", 1); } int @@ -113,19 +150,24 @@ evsignal_recalc(sigset_t *evsigmask) struct sigaction sa; struct event *ev; + if (!ev_signal_added) { + ev_signal_added = 1; + event_add(&ev_signal, NULL); + } + if (TAILQ_FIRST(&signalqueue) == NULL && !needrecalc) return (0); needrecalc = 0; if (sigprocmask(SIG_BLOCK, evsigmask, NULL) == -1) return (-1); - + /* Reinstall our signal handler. */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = evsignal_handler; sa.sa_mask = *evsigmask; sa.sa_flags |= SA_RESTART; - + TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { if (sigaction(EVENT_SIGNAL(ev), &sa, NULL) == -1) return (-1); |