From: Roy Marples Date: Mon, 18 Feb 2013 15:40:56 +0000 (+0000) Subject: Restore our signal pipe so that we process signals in our event loop X-Git-Tag: v5.99.6~60 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cf6d21215b04c8491db186ab8f2e85c09a095cb4;p=thirdparty%2Fdhcpcd.git Restore our signal pipe so that we process signals in our event loop as we use a lot of functions which are not safe according to signal(7). --- diff --git a/dhcpcd.c b/dhcpcd.c index 69898c38..3fc05cc9 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -1130,7 +1130,7 @@ main(int argc, char **argv) * when we're testing fd's. * This allows us to ensure a consistent state is maintained * regardless of when we are interrupted .*/ - if (signal_setup(handle_signal, &dhcpcd_sigset) == -1) { + if (signal_init(handle_signal, &dhcpcd_sigset) == -1) { syslog(LOG_ERR, "signal_setup: %m"); exit(EXIT_FAILURE); } diff --git a/signals.c b/signals.c index 3602fae8..fb101c06 100644 --- a/signals.c +++ b/signals.c @@ -32,8 +32,12 @@ #include #include "common.h" +#include "eloop.h" #include "signals.h" +static int signal_pipe[2]; +static void (*signal_callback)(int); + const int handle_sigs[] = { SIGALRM, SIGHUP, @@ -44,6 +48,31 @@ const int handle_sigs[] = { 0 }; +static void +signal_handler(int sig) +{ + int serrno = errno; + + if (write(signal_pipe[1], &sig, sizeof(sig)) != sizeof(sig)) + syslog(LOG_ERR, "%s: write: %m", __func__); + errno = serrno; +} + +static void +signal_read(_unused void *arg) +{ + int sig = -1; + char buf[16]; + ssize_t bytes; + + memset(buf, 0, sizeof(buf)); + bytes = read(signal_pipe[0], buf, sizeof(buf)); + if (signal_callback && bytes >= 0 && (size_t)bytes >= sizeof(sig)) { + memcpy(&sig, buf, sizeof(sig)); + signal_callback(sig); + } +} + static int signal_handle(void (*func)(int), sigset_t *oldset) { @@ -70,15 +99,21 @@ signal_handle(void (*func)(int), sigset_t *oldset) } int -signal_setup(void (*func)(int), sigset_t *oldset) +signal_init(void (*func)(int), sigset_t *oldset) { - return signal_handle(func, oldset); -} - -int -signal_reset(void) -{ + if (pipe(signal_pipe) == -1) + return -1; + if (set_nonblock(signal_pipe[0]) == -1) + return -1; + if (set_cloexec(signal_pipe[0]) == -1 || + set_cloexec(signal_pipe[1] == -1)) + return -1; - return signal_handle(SIG_DFL, NULL); + /* Because functions we need to reboot/reconf out interfaces + * are not async signal safe, we need to setup a signal pipe + * so that the actual handler is executed in our event loop. */ + signal_callback = func; + eloop_event_add(signal_pipe[0], signal_read, NULL); + return signal_handle(signal_handler, oldset); } diff --git a/signals.h b/signals.h index bd141329..9e674202 100644 --- a/signals.h +++ b/signals.h @@ -30,10 +30,6 @@ extern const int handle_sigs[]; -int signal_init(void); -int signal_setup(void (*)(int), sigset_t *); -int signal_reset(void); -int signal_read(void); -int signal_block(int); +int signal_init(void (*)(int), sigset_t *); #endif