#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;
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);
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;
}
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;
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)
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);
}
/**
}
/**
- * 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));
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);
}
/**