From 2a2d1f8d52477af7e6e161d60c722b7a2f1a4651 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 16 Mar 2008 20:37:46 +0100 Subject: [PATCH] Implement signal handling. --- dss.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- exec.c | 4 ++++ signal.c | 30 ++++++++++++++++++++---------- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/dss.c b/dss.c index f65a29f..3612d4f 100644 --- a/dss.c +++ b/dss.c @@ -23,11 +23,13 @@ #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; +int signal_pipe; 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 (;;) { - ret = waitpid(pid, status, 0); - if (ret >= 0 || errno != EINTR) + pause(); + ret = next_signal(); + if (ret < 0) 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); @@ -446,10 +460,15 @@ int wait_for_rm_process(pid_t pid) int com_run(void) { + int ret; + 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; } @@ -708,6 +727,28 @@ int check_config(void) 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; @@ -728,11 +769,12 @@ int main(int argc, char **argv) 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; + if (conf.daemon_given) + daemon_init(); + setup_signal_handling(); ret = call_command_handler(); out: if (ret < 0) diff --git a/exec.c b/exec.c index 13a0e4b..e796ebf 100644 --- a/exec.c +++ b/exec.c @@ -7,6 +7,7 @@ #include #include #include +#include #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); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGCHLD, SIG_DFL); execvp(file, args); _exit(EXIT_FAILURE); } diff --git a/signal.c b/signal.c index 160730f..c82e58b 100644 --- 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)); - //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. + * * \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. * - * \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 s; + int s, err; 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; } - 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); } /** -- 2.39.2