]> git.tuebingen.mpg.de Git - dss.git/blobdiff - dss.c
kill: New option --wait.
[dss.git] / dss.c
diff --git a/dss.c b/dss.c
index 5e2ef46f71251c6a157f2f9df02900c8e534a3a9..60c05916424e5336401abb6ee284049fdfb5dc04 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -282,11 +282,13 @@ static char *get_config_file_name(void)
        return config_file;
 }
 
-static int send_signal(int sig)
+static int send_signal(int sig, bool wait)
 {
        pid_t pid;
        char *config_file = get_config_file_name();
        int ret = get_dss_pid(config_file, &pid);
+       unsigned ms = 32;
+       struct timespec ts;
 
        free(config_file);
        if (ret < 0)
@@ -298,7 +300,23 @@ static int send_signal(int sig)
        ret = kill(pid, sig);
        if (ret < 0)
                return -ERRNO_TO_DSS_ERROR(errno);
-       return 1;
+       if (!wait)
+               return 1;
+       while (ms < 5000) {
+               ts.tv_sec = ms / 1000;
+               ts.tv_nsec = (ms % 1000) * 1000 * 1000;
+               ret = nanosleep(&ts, NULL);
+               if (ret < 0)
+                       return -ERRNO_TO_DSS_ERROR(errno);
+               ret = kill(pid, 0);
+               if (ret < 0) {
+                       if (errno != ESRCH)
+                               return -ERRNO_TO_DSS_ERROR(errno);
+                       return 1;
+               }
+               ms *= 2;
+       }
+       return -E_KILL_TIMEOUT;
 }
 
 struct signal_info {
@@ -357,6 +375,7 @@ static const struct signal_info signal_table[] = {
 
 static int com_kill(void)
 {
+       bool w_given = OPT_GIVEN(KILL, WAIT);
        const char *arg = OPT_STRING_VAL(KILL, SIGNAL);
        int ret, i;
 
@@ -367,17 +386,17 @@ static int com_kill(void)
                        return ret;
                if (val < 0 || val > SIGRTMAX)
                        return -ERRNO_TO_DSS_ERROR(EINVAL);
-               return send_signal(val);
+               return send_signal(val, w_given);
        }
        if (strncasecmp(arg, "sig", 3) == 0)
                arg += 3;
        if (strcasecmp(arg, "CLD") == 0)
-               return send_signal(SIGCHLD);
+               return send_signal(SIGCHLD, w_given);
        if (strcasecmp(arg, "IOT") == 0)
-               return send_signal(SIGABRT);
+               return send_signal(SIGABRT, w_given);
        for (i = 0; i < SIGNAL_TABLE_SIZE; i++)
                if (strcasecmp(arg, signal_table[i].name) == 0)
-                       return send_signal(signal_table[i].num);
+                       return send_signal(signal_table[i].num, w_given);
        DSS_ERROR_LOG(("invalid sigspec: %s\n", arg));
        return -ERRNO_TO_DSS_ERROR(EINVAL);
 }
@@ -1347,6 +1366,7 @@ static void create_rsync_argv(char ***argv, int64_t *num)
        char *logname;
        int i = 0, j, N = OPT_GIVEN(DSS, RSYNC_OPTION);
        struct snapshot_list sl;
+       static bool seeded;
 
        dss_get_snapshot_list(&sl);
        assert(!name_of_reference_snapshot);
@@ -1357,6 +1377,14 @@ static void create_rsync_argv(char ***argv, int64_t *num)
        (*argv)[i++] = dss_strdup("rsync");
        (*argv)[i++] = dss_strdup("-a");
        (*argv)[i++] = dss_strdup("--delete");
+       if (!seeded) {
+               srandom((unsigned)time(NULL)); /* no need to be fancy here */
+               seeded = true;
+       }
+       if (1000 * (random() / (RAND_MAX + 1.0)) < OPT_UINT32_VAL(DSS, CHECKSUM)) {
+               DSS_NOTICE_LOG(("adding --checksum to rsync options\n"));
+               (*argv)[i++] = dss_strdup("--checksum");
+       }
        for (j = 0; j < N; j++)
                (*argv)[i++] = dss_strdup(lls_string_val(j,
                        OPT_RESULT(DSS, RSYNC_OPTION)));
@@ -1556,6 +1584,8 @@ static int com_run(void)
                ret = -E_BUG;
        kill_children();
        exit_hook(ret);
+       while (wait(NULL) >= 0 || errno != ECHILD)
+               ; /* still have children to wait for */
        return ret;
 }
 EXPORT_CMD_HANDLER(run);