Kill children on fatal errors.
authorAndre Noll <maan@systemlinux.org>
Wed, 16 Oct 2013 12:17:46 +0000 (14:17 +0200)
committerAndre Noll <maan@systemlinux.org>
Wed, 16 Oct 2013 12:28:33 +0000 (14:28 +0200)
If dss is about to die because it received SIGINT or SIGTERM, we first
restart the rsync process by sending SIGCONT, then send SIGTERM to
both the rsync and the rm process to get rid of any child processes.

This works fine, but there are other fatal errors for which we miss
to clean up as thoroughly, most importantly if there is not enough
free disk space for a single snapshot.

This patch moves the signal-related cleanup part to the new function
kill_children(), and changes handle_signal() and com_run() to call
this function right before the exit hook is invoked.

dss.c

diff --git a/dss.c b/dss.c
index 237208b7da0a0f3a8f14c2e86c4cbce7cb1fe735..3a2f46886c310f23b987665854c99e75334e44b0 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -1038,6 +1038,13 @@ static int handle_sighup(void)
        return change_to_dest_dir();
 }
 
        return change_to_dest_dir();
 }
 
+static void kill_children(void)
+{
+       restart_create_process();
+       dss_kill(create_pid, SIGTERM, NULL);
+       dss_kill(remove_pid, SIGTERM, NULL);
+}
+
 static int handle_signal(void)
 {
        int sig, ret = next_signal();
 static int handle_signal(void)
 {
        int sig, ret = next_signal();
@@ -1048,9 +1055,7 @@ static int handle_signal(void)
        switch (sig) {
        case SIGINT:
        case SIGTERM:
        switch (sig) {
        case SIGINT:
        case SIGTERM:
-               restart_create_process();
-               dss_kill(create_pid, SIGTERM, NULL);
-               dss_kill(remove_pid, SIGTERM, NULL);
+               kill_children();
                ret = -E_SIGNAL;
                break;
        case SIGHUP:
                ret = -E_SIGNAL;
                break;
        case SIGHUP:
@@ -1319,6 +1324,7 @@ static int com_run(void)
        ret = select_loop();
        if (ret >= 0) /* impossible */
                ret = -E_BUG;
        ret = select_loop();
        if (ret >= 0) /* impossible */
                ret = -E_BUG;
+       kill_children();
        exit_hook(ret);
        return ret;
 }
        exit_hook(ret);
        return ret;
 }