From: Roy Marples Date: Tue, 12 May 2015 14:14:32 +0000 (+0000) Subject: Move signal handling into eloop with just the callback in dhcpcd. X-Git-Tag: v6.9.0~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d22c40d3793b08d52a17f0328c0b8d2b19337b23;p=thirdparty%2Fdhcpcd.git Move signal handling into eloop with just the callback in dhcpcd. This allows a cleaner platform agnostic signal setup in dhcpcd itself. --- diff --git a/dhcpcd.c b/dhcpcd.c index d4546cc0..82c09806 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -76,16 +76,6 @@ const int dhcpcd_signals[] = { SIGPIPE, 0 }; - -#ifndef HAVE_KQUEUE -struct dhcpcd_siginfo { - struct dhcpcd_ctx *ctx; - int sig; -} dhcpcd_siginfo; - -/* Handling signals needs *some* context */ -static struct dhcpcd_ctx *dhcpcd_ctx; -#endif #endif #if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK) @@ -1125,7 +1115,7 @@ stop_all_interfaces(struct dhcpcd_ctx *ctx, int do_release) #ifdef USE_SIGNALS #define sigmsg "received %s, %s" static void -handle_signal2(void *arg, int sig) +signal_cb(int sig, void *arg) { struct dhcpcd_ctx *ctx = arg; struct interface *ifp; @@ -1180,56 +1170,6 @@ handle_signal2(void *arg, int sig) stop_all_interfaces(ctx, do_release); eloop_exit(ctx->eloop, exit_code); } - -#ifndef HAVE_KQUEUE -static void -handle_signal1(void *arg) -{ - struct dhcpcd_siginfo *si = arg; - - handle_signal2(si->ctx, si->sig); -} - -static void -handle_signal(int sig, __unused siginfo_t *siginfo, __unused void *context) -{ - - /* So that we can operate safely under a signal we instruct - * eloop to pass a copy of the siginfo structure to handle_signal1 - * as the very first thing to do. */ - dhcpcd_siginfo.ctx = dhcpcd_ctx; - dhcpcd_siginfo.sig = sig; - eloop_timeout_add_now(dhcpcd_ctx->eloop, - handle_signal1, &dhcpcd_siginfo); -} -#endif - -static int -signal_init(sigset_t *oldset) -{ - sigset_t newset; -#ifndef HAVE_KQUEUE - int i; - struct sigaction sa; -#endif - - sigfillset(&newset); - if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) - return -1; - -#ifndef HAVE_KQUEUE - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = handle_signal; - sa.sa_flags = SA_SIGINFO; - sigemptyset(&sa.sa_mask); - - for (i = 0; dhcpcd_signals[i]; i++) { - if (sigaction(dhcpcd_signals[i], &sa, NULL) == -1) - return -1; - } -#endif - return 0; -} #endif static void @@ -1569,8 +1509,7 @@ main(int argc, char **argv) /* Freeing allocated addresses from dumping leases can trigger * eloop removals as well, so init here. */ - ctx.eloop = eloop_init(&ctx, handle_signal2, dhcpcd_signals); - if (ctx.eloop == NULL) { + if ((ctx.eloop = eloop_new()) == NULL) { logger(&ctx, LOG_ERR, "%s: eloop_init: %m", __func__); goto exit_failure; } @@ -1758,9 +1697,15 @@ main(int argc, char **argv) logger(&ctx, LOG_DEBUG, PACKAGE "-" VERSION " starting"); ctx.options |= DHCPCD_STARTED; #ifdef USE_SIGNALS + if (eloop_signal_set_cb(ctx.eloop, dhcpcd_signals, + signal_cb, &ctx) == -1) + { + logger(&ctx, LOG_ERR, "eloop_signal_mask: %m"); + goto exit_failure; + } /* Save signal mask, block and redirect signals to our handler */ - if (signal_init(&ctx.sigset) == -1) { - logger(&ctx, LOG_ERR, "signal_setup: %m"); + if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) { + logger(&ctx, LOG_ERR, "eloop_signal_mask: %m"); goto exit_failure; } #endif diff --git a/eloop.c b/eloop.c index 001a92fe..7058f5b3 100644 --- a/eloop.c +++ b/eloop.c @@ -27,6 +27,7 @@ #include +#include #include #include #include @@ -43,7 +44,7 @@ #include "common.h" #include "dhcpcd.h" #define syslog(PRIO, FMT, ...) \ - logger((struct dhcpcd_ctx *)ctx->cb_ctx, PRIO, FMT, __VA_ARGS__) + logger((struct dhcpcd_ctx *)ctx->signal_cb_ctx, PRIO, FMT, __VA_ARGS__) #if defined(HAVE_KQUEUE) #include @@ -326,7 +327,7 @@ eloop_q_timeout_add_sec(struct eloop_ctx *ctx, int queue, time_t when, } #if !defined(HAVE_KQUEUE) -int +static int eloop_timeout_add_now(struct eloop_ctx *ctx, void (*callback)(void *), void *arg) { @@ -458,8 +459,78 @@ eloop_requeue(struct eloop_ctx *ctx) } #endif +int +eloop_signal_set_cb(struct eloop_ctx *ctx, + const int *signals, void (*signal_cb)(int, void *), void *signal_cb_ctx) +{ + + assert(ctx); + ctx->signals = signals; + ctx->signal_cb = signal_cb; + ctx->signal_cb_ctx = signal_cb_ctx; + return eloop_requeue(ctx); +} + +#ifndef HAVE_KQUEUE +struct eloop_siginfo { + int sig; + struct eloop_ctx *ctx; +}; +static struct eloop_siginfo eloop_siginfo; +static struct eloop_ctx *eloop_ctx; + +static void +eloop_signal1(void *arg) +{ + struct eloop_siginfo *si = arg; + + si->ctx->signal_cb(si->cig, si->ctx->signal_cb_arg); +} + +static void +eloop_signal3(int sig, __unused siginfo_t *siginfo, __unused void *arg) +{ + + /* So that we can operate safely under a signal we instruct + * eloop to pass a copy of the siginfo structure to handle_signal1 + * as the very first thing to do. */ + eloop_siginfo.sig = sig; + eloop_siginfo.ctx = eloop_ctx; + eloop_timeout_add_now(eloop_ctx, eloop_signal1, &eloop_siginfo); +} +#endif + +int +eloop_signal_mask(struct eloop_ctx *ctx, sigset_t *oldset) +{ + sigset_t newset; +#ifndef HAVE_KQUEUE + int i; + struct sigaction sa; +#endif + + sigfillset(&newset); + if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) + return -1; + +#ifdef HAVE_KQUEUE + UNUSED(ctx); +#else + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = eloop_signal3; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + + for (i = 0; ctx->signals[i]; i++) { + if (sigaction(ctx->signals[i], &sa, NULL) == -1) + return -1; + } +#endif + return 0; +} + struct eloop_ctx * -eloop_init(void *ectx, void (*signal_cb)(void *, int), const int *signals) +eloop_new(void) { struct eloop_ctx *ctx; struct timespec now; @@ -470,8 +541,6 @@ eloop_init(void *ectx, void (*signal_cb)(void *, int), const int *signals) ctx = calloc(1, sizeof(*ctx)); if (ctx) { - ctx->cb_ctx = ectx; - ctx->signal_cb = signal_cb; TAILQ_INIT(&ctx->events); TAILQ_INIT(&ctx->free_events); TAILQ_INIT(&ctx->timeouts); @@ -480,11 +549,6 @@ eloop_init(void *ectx, void (*signal_cb)(void *, int), const int *signals) #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) ctx->poll_fd = -1; #endif - ctx->signals = signals; - if (eloop_requeue(ctx) == -1) { - free(ctx); - return NULL; - } } return ctx; @@ -610,7 +674,8 @@ eloop_start(struct eloop_ctx *ctx, sigset_t *signals) #if defined(HAVE_KQUEUE) if (n) { if (ke.filter == EVFILT_SIGNAL) { - ctx->signal_cb(ctx->cb_ctx, (int)ke.ident); + ctx->signal_cb((int)ke.ident, + ctx->signal_cb_ctx); continue; } e = (struct eloop_event *)ke.udata; diff --git a/eloop.h b/eloop.h index 08737887..0969f776 100644 --- a/eloop.h +++ b/eloop.h @@ -61,8 +61,6 @@ struct eloop_timeout { }; struct eloop_ctx { - void *cb_ctx; - size_t events_len; TAILQ_HEAD (event_head, eloop_event) events; struct event_head free_events; @@ -73,7 +71,8 @@ struct eloop_ctx { void (*timeout0)(void *); void *timeout0_arg; const int *signals; - void (*signal_cb)(void *, int); + void (*signal_cb)(int, void *); + void *signal_cb_ctx; #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) int poll_fd; @@ -86,26 +85,29 @@ struct eloop_ctx { int exitcode; }; +int eloop_event_add(struct eloop_ctx *, int, + void (*)(void *), void *, + void (*)(void *), void *); +void eloop_event_delete(struct eloop_ctx *, int, int); + + #define eloop_timeout_add_tv(a, b, c, d) \ eloop_q_timeout_add_tv(a, ELOOP_QUEUE, b, c, d) #define eloop_timeout_add_sec(a, b, c, d) \ eloop_q_timeout_add_sec(a, ELOOP_QUEUE, b, c, d) #define eloop_timeout_delete(a, b, c) \ eloop_q_timeout_delete(a, ELOOP_QUEUE, b, c) - -int eloop_event_add(struct eloop_ctx *, int, - void (*)(void *), void *, - void (*)(void *), void *); -void eloop_event_delete(struct eloop_ctx *, int, int); int eloop_q_timeout_add_sec(struct eloop_ctx *, int queue, time_t, void (*)(void *), void *); int eloop_q_timeout_add_tv(struct eloop_ctx *, int queue, const struct timespec *, void (*)(void *), void *); -#if !defined(HAVE_KQUEUE) -int eloop_timeout_add_now(struct eloop_ctx *, void (*)(void *), void *); -#endif void eloop_q_timeout_delete(struct eloop_ctx *, int, void (*)(void *), void *); -struct eloop_ctx * eloop_init(void *, void (*)(void *, int), const int *); + +int eloop_signal_set_cb(struct eloop_ctx *, const int *, + void (*)(int, void *), void *); +int eloop_signal_mask(struct eloop_ctx *ctx, sigset_t *oldset); + +struct eloop_ctx * eloop_new(void); #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) int eloop_requeue(struct eloop_ctx *); #else