#include "script.h"
#ifdef USE_SIGNALS
-const int dhcpcd_handlesigs[] = {
+const int dhcpcd_signals[] = {
SIGTERM,
SIGINT,
SIGALRM,
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)
static pid_t
}
#ifdef USE_SIGNALS
-struct dhcpcd_siginfo dhcpcd_siginfo;
#define sigmsg "received %s, %s"
-void
-dhcpcd_handle_signal(void *arg)
+static void
+handle_signal2(void *arg, int sig)
{
- struct dhcpcd_ctx *ctx;
- struct dhcpcd_siginfo *si;
+ struct dhcpcd_ctx *ctx = arg;
struct interface *ifp;
- int do_release, exit_code;;
+ int do_release, exit_code;
ctx = dhcpcd_ctx;
- si = arg;
do_release = 0;
exit_code = EXIT_FAILURE;
- switch (si->signo) {
+ switch (sig) {
case SIGINT:
logger(ctx, LOG_INFO, sigmsg, "SIGINT", "stopping");
break;
logger(ctx, LOG_ERR,
"received signal %d, "
"but don't know what to do with it",
- si->signo);
+ sig);
return;
}
}
#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.signo = sig;
+ dhcpcd_siginfo.ctx = dhcpcd_ctx;
+ dhcpcd_siginfo.sig = sig;
eloop_timeout_add_now(dhcpcd_ctx->eloop,
- dhcpcd_handle_signal, &dhcpcd_siginfo);
+ handle_signal1, &dhcpcd_siginfo);
}
#endif
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
- for (i = 0; dhcpcd_handlesigs[i]; i++) {
- if (sigaction(dhcpcd_handlesigs[i], &sa, NULL) == -1)
+ for (i = 0; dhcpcd_signals[i]; i++) {
+ if (sigaction(dhcpcd_signals[i], &sa, NULL) == -1)
return -1;
}
#endif
/* Freeing allocated addresses from dumping leases can trigger
* eloop removals as well, so init here. */
- ctx.eloop = eloop_init(&ctx);
+ ctx.eloop = eloop_init(&ctx, handle_signal2, dhcpcd_signals);
if (ctx.eloop == NULL) {
logger(&ctx, LOG_ERR, "%s: eloop_init: %m", __func__);
goto exit_failure;
dhcpcd_prestartinterface, ifp);
}
- i = eloop_start(ctx.eloop);
+ i = eloop_start(ctx.eloop, &ctx.sigset);
goto exit1;
exit_success:
#include <signal.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
#include <unistd.h>
+/* config.h should define HAVE_KQUEUE, HAVE_EPOLL, etc */
#include "config.h"
+#include "eloop.h"
+
+/* custom syslog wrapper for dhcpcd */
#include "common.h"
#include "dhcpcd.h"
-#include "eloop.h"
+#define syslog(PRIO, FMT, ...) \
+ logger((struct dhcpcd_ctx *)ctx->cb_ctx, PRIO, FMT, __VA_ARGS__)
#if defined(HAVE_KQUEUE)
#include <sys/event.h>
return 0;
err:
- logger(ctx->ctx, LOG_ERR, "%s: %m", __func__);
+ syslog(LOG_ERR, "%s: %m", __func__);
if (e) {
ctx->events_len--;
TAILQ_INSERT_TAIL(&ctx->free_events, e, next);
} else {
t = malloc(sizeof(*t));
if (t == NULL) {
- logger(ctx->ctx, LOG_ERR, "%s: %m", __func__);
+ syslog(LOG_ERR, "%s: %m", __func__);
return -1;
}
}
{
if (ctx->timeout0 != NULL) {
- logger(ctx->ctx, LOG_WARNING,
- "%s: timeout0 already set", __func__);
+ syslog(LOG_WARNING, "%s: timeout0 already set", __func__);
return eloop_q_timeout_add_sec(ctx, 0, 0, callback, arg);
}
return -1;
#if defined (HAVE_KQUEUE)
i = 0;
- while (dhcpcd_handlesigs[i])
+ while (ctx->signals[i] != 0)
i++;
TAILQ_FOREACH(e, &ctx->events, next) {
i++;
if ((ke = malloc(sizeof(*ke) * i)) == NULL)
return -1;
- for (i = 0; dhcpcd_handlesigs[i]; i++)
- EV_SET(&ke[i], (uintptr_t)dhcpcd_handlesigs[i],
+ for (i = 0; ctx->signal[i] != 0; i++)
+ EV_SET(&ke[i], (uintptr_t)ctx->signals[i],
EVFILT_SIGNAL, EV_ADD, 0, 0, UPTR(NULL));
TAILQ_FOREACH(e, &ctx->events, next) {
#endif
struct eloop_ctx *
-eloop_init(struct dhcpcd_ctx *dctx)
+eloop_init(void *ectx, void (*signal_cb)(void *, int), const int *signals)
{
struct eloop_ctx *ctx;
struct timespec now;
ctx = calloc(1, sizeof(*ctx));
if (ctx) {
- ctx->ctx = dctx;
+ 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;
}
int
-eloop_start(struct eloop_ctx *ctx)
+eloop_start(struct eloop_ctx *ctx, sigset_t *signals)
{
int n;
struct eloop_event *e;
#endif
#if defined(HAVE_KQUEUE)
struct kevent ke;
+ UNUSED(signals);
#elif defined(HAVE_EPOLL)
struct epoll_event epe;
#endif
continue;
}
if ((t = TAILQ_FIRST(&ctx->timeouts))) {
- get_monotonic(&now);
+ clock_gettime(CLOCK_MONOTONIC, &now);
if (timespeccmp(&now, &t->when, >)) {
TAILQ_REMOVE(&ctx->timeouts, t, next);
t->callback(t->arg);
tsp = NULL;
if (tsp == NULL && ctx->events_len == 0) {
- logger(ctx->ctx, LOG_ERR, "nothing to do");
+ syslog(LOG_ERR, "%s: nothing to do", __func__);
break;
}
n = kevent(ctx->poll_fd, NULL, 0, &ke, 1, tsp);
#elif defined(HAVE_EPOLL)
#ifdef USE_SIGNALS
- n = epoll_pwait(ctx->poll_fd, &epe, 1, timeout,
- &ctx->ctx->sigset);
+ n = epoll_pwait(ctx->poll_fd, &epe, 1, timeout, signals);
#else
n = epoll_wait(ctx->poll_fd, &epe, 1, timeout);
#endif
#else
#ifdef USE_SIGNALS
- n = pollts(ctx->fds, (nfds_t)ctx->events_len, tsp,
- &ctx->ctx->sigset);
+ n = pollts(ctx->fds, (nfds_t)ctx->events_len, tsp, signals);
#else
n = poll(ctx->fds, (nfds_t)ctx->events_len, timeout);
#endif
if (n == -1) {
if (errno == EINTR)
continue;
- logger(ctx->ctx, LOG_ERR, "poll: %m");
+ syslog(LOG_ERR, "%s: poll: %m", __func__);
break;
}
#if defined(HAVE_KQUEUE)
if (n) {
if (ke.filter == EVFILT_SIGNAL) {
- struct dhcpcd_siginfo si;
-
- si.signo = (int)ke.ident;
- dhcpcd_handle_signal(&si);
+ ctx->signal_cb(ctx->cb_ctx, (int)ke.ident);
continue;
}
e = (struct eloop_event *)ke.udata;
};
struct eloop_ctx {
- struct dhcpcd_ctx *ctx;
+ void *cb_ctx;
size_t events_len;
TAILQ_HEAD (event_head, eloop_event) events;
void (*timeout0)(void *);
void *timeout0_arg;
+ const int *signals;
+ void (*signal_cb)(void *, int);
#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
int poll_fd;
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(struct dhcpcd_ctx *);
+struct eloop_ctx * eloop_init(void *, void (*)(void *, int), const int *);
#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
int eloop_requeue(struct eloop_ctx *);
#else
-#define eloop_requeue(a) (0)
+#define eloop_requeue(a, b) (0)
#endif
void eloop_free(struct eloop_ctx *);
void eloop_exit(struct eloop_ctx *, int);
-int eloop_start(struct eloop_ctx *);
+int eloop_start(struct eloop_ctx *, sigset_t *);
#endif