This allows a cleaner platform agnostic signal setup in dhcpcd itself.
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)
#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;
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
/* 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;
}
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
#include <sys/time.h>
+#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#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>
}
#if !defined(HAVE_KQUEUE)
-int
+static int
eloop_timeout_add_now(struct eloop_ctx *ctx,
void (*callback)(void *), void *arg)
{
}
#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;
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);
#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;
#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;
};
struct eloop_ctx {
- void *cb_ctx;
-
size_t events_len;
TAILQ_HEAD (event_head, eloop_event) events;
struct event_head free_events;
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;
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