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 01f1bc71648157cf4de5ad085bc945887b81c376..63f5f568fd735a8470f54d8df1663e243de81c06 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(ls) \
        COMMAND(create) \
        COMMAND(prune) \
-       COMMAND(run)
+       COMMAND(run) \
+       COMMAND(kill)
 #define COMMAND(x) static int com_ ##x(void);
 COMMANDS
 #undef COMMAND
 #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;
 }
 
        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);
 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 1662e0d36f514491c1029e674bc407a98012942d..c594f6e62ef81eacf8c576ede3dc908a9bfe9f58 100644 (file)
--- a/dss.ggo
+++ b/dss.ggo
@@ -145,6 +145,16 @@ details="
        received. See also the --exit-hook option.
 "
 
        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"
 ###############################
 ###############################
 section "Rsync-related options"
 ###############################
diff --git a/error.h b/error.h
index 9e910e2b2236bb9dae79b1d1df36ea0cb5a27b3a..3fd75313406670a5683dde315a817c7903420f27 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(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 8d969c74385fc77a54229373f8e848a5ffc69346..053e0fd99afcdb94f3d0ba9789a51a31f6c77106 100644 (file)
--- a/ipc.c
+++ b/ipc.c
@@ -313,6 +313,29 @@ static int mutex_lock(int id)
        return 1;
 }
 
        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);
 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);
 }
                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 4d644427864afa537645ac2ac0f97fa2f340c20a..8646a8e1a718d2060431dea26b3e8372a2c1b3b8 100644 (file)
--- a/ipc.h
+++ b/ipc.h
@@ -1 +1,2 @@
 int lock_dss(char *config_file);
 int lock_dss(char *config_file);
+int get_dss_pid(char *config_file, pid_t *pid);