Move signal handling into eloop with just the callback in dhcpcd.

This allows a cleaner platform agnostic signal setup in dhcpcd itself.
This commit is contained in:
Roy Marples 2015-05-12 14:14:32 +00:00
parent b3f1735bbf
commit d22c40d379
3 changed files with 100 additions and 88 deletions

View File

@ -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

87
eloop.c
View File

@ -27,6 +27,7 @@
#include <sys/time.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
@ -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 <sys/event.h>
@ -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;

26
eloop.h
View File

@ -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