Implement signal handling.
authorAndre Noll <maan@systemlinux.org>
Sun, 16 Mar 2008 19:37:46 +0000 (20:37 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 16 Mar 2008 19:37:46 +0000 (20:37 +0100)
dss.c
exec.c
signal.c

diff --git a/dss.c b/dss.c
index f65a29f..3612d4f 100644 (file)
--- a/dss.c
+++ b/dss.c
 #include "fd.h"
 #include "exec.h"
 #include "daemon.h"
 #include "fd.h"
 #include "exec.h"
 #include "daemon.h"
+#include "signal.h"
 
 
 struct gengetopt_args_info conf;
 char *dss_error_txt = NULL;
 static FILE *logfile;
 
 
 struct gengetopt_args_info conf;
 char *dss_error_txt = NULL;
 static FILE *logfile;
+int signal_pipe;
 
 DEFINE_DSS_ERRLIST;
 
 
 DEFINE_DSS_ERRLIST;
 
@@ -316,9 +318,21 @@ int wait_for_process(pid_t pid, int *status)
 
        DSS_DEBUG_LOG("Waiting for process %d to terminate\n", (int)pid);
        for (;;) {
 
        DSS_DEBUG_LOG("Waiting for process %d to terminate\n", (int)pid);
        for (;;) {
-               ret = waitpid(pid, status, 0);
-               if (ret >= 0 || errno != EINTR)
+               pause();
+               ret = next_signal();
+               if  (ret < 0)
                        break;
                        break;
+               if (!ret)
+                       continue;
+               if (ret == SIGCHLD) {
+                       ret = waitpid(pid, status, 0);
+                       if (ret >= 0)
+                               break;
+                       if (errno != EINTR) /* error */
+                               break;
+               }
+               DSS_WARNING_LOG("sending SIGTERM to pid %d\n", (int)pid);
+               kill(pid, SIGTERM);
        }
        if (ret < 0) {
                ret = -ERRNO_TO_DSS_ERROR(errno);
        }
        if (ret < 0) {
                ret = -ERRNO_TO_DSS_ERROR(errno);
@@ -446,10 +460,15 @@ int wait_for_rm_process(pid_t pid)
 
 int com_run(void)
 {
 
 int com_run(void)
 {
+       int ret;
+
        if (conf.dry_run_given) {
                make_err_msg("dry_run not supported by this command");
                return -E_SYNTAX;
        }
        if (conf.dry_run_given) {
                make_err_msg("dry_run not supported by this command");
                return -E_SYNTAX;
        }
+       ret = install_sighandler(SIGHUP);
+       if (ret < 0)
+               return ret;
        return 42;
 }
 
        return 42;
 }
 
@@ -708,6 +727,28 @@ int check_config(void)
        return 1;
 }
 
        return 1;
 }
 
+static void setup_signal_handling(void)
+{
+       int ret;
+
+       DSS_NOTICE_LOG("setting up signal handlers\n");
+       signal_pipe = signal_init(); /* always successful */
+       ret = install_sighandler(SIGINT);
+       if (ret < 0)
+               goto err;
+       ret = install_sighandler(SIGTERM);
+       if (ret < 0)
+               goto err;
+       ret = install_sighandler(SIGCHLD);
+       if (ret < 0)
+               goto err;
+       return;
+err:
+       DSS_EMERG_LOG("could not install signal handlers\n");
+       exit(EXIT_FAILURE);
+}
+
+
 int main(int argc, char **argv)
 {
        int ret;
 int main(int argc, char **argv)
 {
        int ret;
@@ -728,11 +769,12 @@ int main(int argc, char **argv)
                logfile = open_log(conf.logfile_arg);
                log_welcome(conf.loglevel_arg);
        }
                logfile = open_log(conf.logfile_arg);
                log_welcome(conf.loglevel_arg);
        }
-       if (conf.daemon_given)
-               daemon_init();
        ret = dss_chdir(conf.dest_dir_arg);
        if (ret < 0)
                goto out;
        ret = dss_chdir(conf.dest_dir_arg);
        if (ret < 0)
                goto out;
+       if (conf.daemon_given)
+               daemon_init();
+       setup_signal_handling();
        ret = call_command_handler();
 out:
        if (ret < 0)
        ret = call_command_handler();
 out:
        if (ret < 0)
diff --git a/exec.c b/exec.c
index 13a0e4b..e796ebf 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -7,6 +7,7 @@
 #include <unistd.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <assert.h>
 #include <stdlib.h>
+#include <signal.h>
 
 
 #include "gcc-compat.h"
 
 
 #include "gcc-compat.h"
@@ -73,6 +74,9 @@ int dss_exec(pid_t *pid, const char *file, char *const *const args, int *fds)
                }
                if (null >= 0)
                        close(null);
                }
                if (null >= 0)
                        close(null);
+               signal(SIGINT, SIG_DFL);
+               signal(SIGTERM, SIG_DFL);
+               signal(SIGCHLD, SIG_DFL);
                execvp(file, args);
                _exit(EXIT_FAILURE);
        }
                execvp(file, args);
                _exit(EXIT_FAILURE);
        }
index 160730f..c82e58b 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -69,7 +69,7 @@ err_out:
 static void generic_signal_handler(int s)
 {
        write(signal_pipe[1], &s, sizeof(int));
 static void generic_signal_handler(int s)
 {
        write(signal_pipe[1], &s, sizeof(int));
-       //fprintf(stderr, "got sig %i, write returned %d\n", s, ret);
+       //fprintf(stderr, "got sig %i\n", s);
 }
 
 /**
 }
 
 /**
@@ -107,31 +107,36 @@ int reap_child(pid_t *pid)
 }
 
 /**
 }
 
 /**
- * wrapper around signal(2)
- * \param sig the number of the signal to catch
+ * Wrapper around signal(2)
+ *
+ * \param sig The number of the signal to catch.
  *
  * This installs the generic signal handler for the given signal.
  *
  * This installs the generic signal handler for the given signal.
+ *
  * \return This function returns 1 on success and \p -E_SIGNAL_SIG_ERR on errors.
  * \sa signal(2)
  */
 int install_sighandler(int sig)
 {
        DSS_DEBUG_LOG("catching signal %d\n", sig);
  * \return This function returns 1 on success and \p -E_SIGNAL_SIG_ERR on errors.
  * \sa signal(2)
  */
 int install_sighandler(int sig)
 {
        DSS_DEBUG_LOG("catching signal %d\n", sig);
-       return signal(sig, &generic_signal_handler) == SIG_ERR?  -E_SIGNAL_SIG_ERR : 1;
+       if (signal(sig, &generic_signal_handler) != SIG_ERR)
+               return 1;
+       make_err_msg("signal %d", sig);
+       return -E_SIGNAL_SIG_ERR;
 }
 
 /**
 }
 
 /**
- * return number of next pending signal
+ * Return number of next pending signal.
  *
  * This should be called if the fd for the signal pipe is ready for reading.
  *
  *
  * This should be called if the fd for the signal pipe is ready for reading.
  *
- * \return On success, the number of the received signal is returned. \p
- * -E_SIGNAL_READ is returned if a read error occurred while reading the signal
- * pipe.  If the read was interrupted by another signal the function returns 0.
+ * \return On success, the number of the received signal is returned.
+ * If the read was interrupted by another signal the function returns 0.
+ * Otherwise a negative error code is returned.
  */
 int next_signal(void)
 {
  */
 int next_signal(void)
 {
-       int s;
+       int s, err;
        ssize_t r;
 
        r = read(signal_pipe[0], &s, sizeof(s));
        ssize_t r;
 
        r = read(signal_pipe[0], &s, sizeof(s));
@@ -139,7 +144,12 @@ int next_signal(void)
                DSS_DEBUG_LOG("next signal: %d\n", s);
                return s;
        }
                DSS_DEBUG_LOG("next signal: %d\n", s);
                return s;
        }
-       return r < 0 && (errno != EAGAIN)? 0 : -ERRNO_TO_DSS_ERROR(errno);
+       err = errno;
+       assert(r < 0);
+       if (err == EAGAIN)
+               return 0;
+       make_err_msg("failed to read from signal pipe");
+       return -ERRNO_TO_DSS_ERROR(err);
 }
 
 /**
 }
 
 /**