]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Restore our signal pipe so that we process signals in our event loop
authorRoy Marples <roy@marples.name>
Mon, 18 Feb 2013 15:40:56 +0000 (15:40 +0000)
committerRoy Marples <roy@marples.name>
Mon, 18 Feb 2013 15:40:56 +0000 (15:40 +0000)
as we use a lot of functions which are not safe according to signal(7).

dhcpcd.c
signals.c
signals.h

index 69898c38b993a141e1894f4113d9088d05f564f7..3fc05cc96852edcb581f64d08b0f5813dea6c7de 100644 (file)
--- 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);
        }
index 3602fae86cfe6ffeb87960fb6e3b003bece645fc..fb101c0692e8b2861db110a1862f731488ed90a2 100644 (file)
--- a/signals.c
+++ b/signals.c
 #include <unistd.h>
 
 #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);
 }
index bd141329adcaa5530a28972c5178b9c4d3bc2168..9e674202f8d1f9f94564089d41ff270e235bbaf6 100644 (file)
--- a/signals.h
+++ b/signals.h
 
 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