Add the --kill subcommand.
authorAndre Noll <maan@systemlinux.org>
Sat, 13 Nov 2010 19:51:28 +0000 (20:51 +0100)
committerAndre Noll <maan@systemlinux.org>
Fri, 1 Jun 2012 15:31:36 +0000 (17:31 +0200)
It works as follows: Whenever a semaphore operation is performed, the
PID of the process is stored in the sempid field of the semaphore.
This PID can be obtained from a different process by calling semctl
with the GETPID command.

com_kill() first tries to acquire the lock by calling the new
mutex_try_lock() function of ipc.c. In contrast to mutex_lock(),
mutex_try_lock() only operates on the first semaphore in the semaphore
set, leaving the sempid field of the second semaphore unchanged. If
mutex_try_lock() succeeds, no running dss process is holding the lock
and the kill command fails. Otherwise, some dss process is running
whose PID can be obtained by calling semctl() on the second semaphore.

dss.c
dss.ggo
error.h
ipc.c
ipc.h

diff --git a/dss.c b/dss.c
index 01f1bc7..63f5f56 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -171,7 +171,8 @@ static void dump_dss_config(const char *msg)
        COMMAND(ls) \
        COMMAND(create) \
        COMMAND(prune) \
-       COMMAND(run)
+       COMMAND(run) \
+       COMMAND(kill)
 #define COMMAND(x) static int com_ ##x(void);
 COMMANDS
 #undef COMMAND
@@ -239,6 +240,25 @@ static char *get_config_file_name(void)
        return config_file;
 }
 
+static int com_kill(void)
+{
+       pid_t pid;
+       char *config_file = get_config_file_name();
+       int ret = get_dss_pid(config_file, &pid);
+
+       free(config_file);
+       if (ret < 0)
+               return ret;
+       if (conf.dry_run_given) {
+               dss_msg("%d\n", (int)pid);
+               return 0;
+       }
+       ret = kill(pid, SIGTERM);
+       if (ret < 0)
+               return -ERRNO_TO_DSS_ERROR(errno);
+       return 1;
+}
+
 static void dss_get_snapshot_list(struct snapshot_list *sl)
 {
        get_snapshot_list(sl, conf.unit_interval_arg, conf.num_intervals_arg);
diff --git a/dss.ggo b/dss.ggo
index 1662e0d..c594f6e 100644 (file)
--- a/dss.ggo
+++ b/dss.ggo
@@ -145,6 +145,16 @@ details="
        received. See also the --exit-hook option.
 "
 
+groupoption "kill" K
+#~~~~~~~~~~~~~~~~~~~
+"Kill a running dss process"
+group="command"
+details="
+       This sends SIGTERM to the dss process that corresponds to the
+       given config file. If --dry-run is given, the PID of the dss
+       process is written to stdout, but no signal is sent.
+"
+
 ###############################
 section "Rsync-related options"
 ###############################
diff --git a/error.h b/error.h
index 9e910e2..3fd7531 100644 (file)
--- a/error.h
+++ b/error.h
@@ -68,6 +68,7 @@ static inline char *dss_strerror(int num)
        DSS_ERROR(SIGNAL_SIG_ERR, "signal() returned SIG_ERR") \
        DSS_ERROR(SIGNAL, "caught terminating signal") \
        DSS_ERROR(BUG, "values of beta might cause dom!") \
+       DSS_ERROR(NOT_RUNNING, "dss not running") \
 
 
 /**
diff --git a/ipc.c b/ipc.c
index 8d969c7..053e0fd 100644 (file)
--- a/ipc.c
+++ b/ipc.c
@@ -313,6 +313,29 @@ static int mutex_lock(int id)
        return 1;
 }
 
+static int mutex_try_lock(int id)
+{
+       int ret;
+
+       DSS_DEBUG_LOG("trying to lock\n");
+       struct sembuf sops[2] = {
+               {
+                       .sem_num = 0,
+                       .sem_op = 0,
+                       .sem_flg = SEM_UNDO | IPC_NOWAIT
+               },
+               {
+                       .sem_num = 0,
+                       .sem_op = 1,
+                       .sem_flg = SEM_UNDO | IPC_NOWAIT
+               }
+       };
+       ret = do_semop(id, sops, 2);
+       if (ret < 0)
+               return -ERRNO_TO_DSS_ERROR(errno);
+       return 1;
+}
+
 int lock_dss(char *config_file)
 {
        int ret, key = get_key_or_die(config_file);
@@ -322,3 +345,21 @@ int lock_dss(char *config_file)
                return ret;
        return mutex_lock(ret);
 }
+
+int get_dss_pid(char *config_file, pid_t *pid)
+{
+       int ret, semid, key = get_key_or_die(config_file);
+
+       ret = mutex_get(key, 0);
+       if (ret < 0)
+               return ret;
+       semid = ret;
+       ret = semctl(semid, 1, GETPID);
+       if (ret < 0)
+               return -E_NOT_RUNNING;
+       *pid = ret;
+       ret = mutex_try_lock(semid);
+       if (ret >= 0)
+               return -E_NOT_RUNNING;
+       return 1;
+}
diff --git a/ipc.h b/ipc.h
index 4d64442..8646a8e 100644 (file)
--- a/ipc.h
+++ b/ipc.h
@@ -1 +1,2 @@
 int lock_dss(char *config_file);
+int get_dss_pid(char *config_file, pid_t *pid);