Merge branch 'refs/heads/t/im-logo'
[dss.git] / sig.c
diff --git a/sig.c b/sig.c
index 9694684045145105001e7410b06558ee73bbfd39..99d3dd34d7ca20c1018e8984d2a362906e07a42a 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2010 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2010 Andre Noll <maan@tuebingen.mpg.de>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -23,6 +23,7 @@
 #include "log.h"
 #include "str.h"
 #include "file.h"
+#include "sig.h"
 
 static int signal_pipe[2];
 
@@ -59,16 +60,31 @@ int signal_init(void)
                goto err_out;
        return signal_pipe[0];
 err_out:
-       DSS_EMERG_LOG("%s\n", dss_strerror(-ret));
+       DSS_EMERG_LOG(("%s\n", dss_strerror(-ret)));
        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)
 {
-       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);
 }
 
 /**
@@ -94,13 +110,13 @@ int reap_child(pid_t *pid, int *status)
        if (*pid < 0)
                return -ERRNO_TO_DSS_ERROR(errno);
        if (WIFEXITED(*status))
-               DSS_DEBUG_LOG("child %i exited. Exit status: %i\n", (int)*pid,
-                       WEXITSTATUS(*status));
+               DSS_DEBUG_LOG(("child %i exited. Exit status: %i\n", (int)*pid,
+                       WEXITSTATUS(*status)));
        else if (WIFSIGNALED(*status))
-               DSS_DEBUG_LOG("child %i was killed by signal %i\n", (int)*pid,
-                       WTERMSIG(*status));
+               DSS_DEBUG_LOG(("child %i was killed by signal %i\n", (int)*pid,
+                       WTERMSIG(*status)));
        else
-               DSS_WARNING_LOG("child %i terminated abormally\n", (int)*pid);
+               DSS_WARNING_LOG(("child %i terminated abormally\n", (int)*pid));
        return 1;
 }
 
@@ -116,7 +132,7 @@ int reap_child(pid_t *pid, int *status)
  */
 int install_sighandler(int sig)
 {
-       DSS_DEBUG_LOG("catching signal %d\n", sig);
+       DSS_DEBUG_LOG(("catching signal %d\n", sig));
        if (signal(sig, &generic_signal_handler) != SIG_ERR)
                return 1;
        return -E_SIGNAL_SIG_ERR;
@@ -138,14 +154,14 @@ int next_signal(void)
 
        r = read(signal_pipe[0], &s, sizeof(s));
        if (r == sizeof(s)) {
-               DSS_DEBUG_LOG("next signal: %d\n", s);
+               DSS_DEBUG_LOG(("next signal: %d\n", s));
                return s;
        }
        err = errno;
        assert(r < 0);
        if (err == EAGAIN)
                return 0;
-       DSS_ERROR_LOG("failed to read from signal pipe\n");
+       DSS_ERROR_LOG(("failed to read from signal pipe\n"));
        return -ERRNO_TO_DSS_ERROR(err);
 }