changeset 1854:c6a5468314d3 draft

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).
author Roy Marples <roy@marples.name>
date Mon, 18 Feb 2013 15:40:56 +0000
parents e6eebb123e36
children 407f259434ff
files dhcpcd.c signals.c signals.h
diffstat 3 files changed, 45 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/dhcpcd.c	Mon Feb 18 10:37:02 2013 +0000
+++ b/dhcpcd.c	Mon Feb 18 15:40:56 2013 +0000
@@ -1130,7 +1130,7 @@
 	 * 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);
 	}
--- a/signals.c	Mon Feb 18 10:37:02 2013 +0000
+++ b/signals.c	Mon Feb 18 15:40:56 2013 +0000
@@ -32,8 +32,12 @@
 #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 @@
 	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 @@
 }
 
 int
-signal_setup(void (*func)(int), sigset_t *oldset)
+signal_init(void (*func)(int), sigset_t *oldset)
 {
 
-	return signal_handle(func, oldset);
-}
+	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;
 
-int
-signal_reset(void)
-{
-
-	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);
 }
--- a/signals.h	Mon Feb 18 10:37:02 2013 +0000
+++ b/signals.h	Mon Feb 18 15:40:56 2013 +0000
@@ -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