Improve signal handler.
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 25 Feb 2015 10:15:33 +0000 (11:15 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Wed, 25 Feb 2015 10:39:48 +0000 (11:39 +0100)
The signal handler of dss has two issues: (a) it does not check the
return value of the write(2) call, and (b) it does not restore errno
on exit. The second issue might cause problems on systems where
write(2) sets errno also on success. Those problems would be very
hard to reproduce and debug. So it is probably a good idea to be
conservative here.

This commit fixes (a) by printing an error message and calling exit(3)
if the write to the signal pipe failed or resulted in a short write.
As for (b), we now save a copy of errno before the write(2) call,
and restore the old value on success.

sig.c

diff --git a/sig.c b/sig.c
index d2d7e3b59076a0c2899d53730bda9aad929f6bc6..99d3dd34d7ca20c1018e8984d2a362906e07a42a 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -64,12 +64,27 @@ err_out:
        exit(EXIT_FAILURE);
 }
 
        exit(EXIT_FAILURE);
 }
 
-/*
- * just write one integer to signal pipe
- */
+/* Write the signal number to the signal pipe, abort on errors. */
 static void generic_signal_handler(int s)
 {
 static void generic_signal_handler(int s)
 {
-       write(signal_pipe[1], &s, sizeof(int));
+       /*
+        * Signal handlers that make system calls must save a copy of errno on
+        * entry to the handler and restore it on exit, to prevent the
+        * possibility of overwriting a errno value that had previously been
+        * set in the main program.
+        */
+       int save_errno = errno;
+       ssize_t ret = write(signal_pipe[1], &s, sizeof(int));
+
+       if (ret == sizeof(int)) {
+               errno = save_errno;
+               return;
+       }
+       if (ret < 0)
+               DSS_EMERG_LOG(("%s\n", strerror(errno)));
+       else
+               DSS_EMERG_LOG(("short write to signal pipe\n"));
+       exit(EXIT_FAILURE);
 }
 
 /**
 }
 
 /**