From: Andre Noll Date: Sat, 13 Nov 2010 19:51:28 +0000 (+0100) Subject: Add the --kill subcommand. X-Git-Tag: v0.1.5~13^2~2 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=492928ebe8b83c31aeca4866fef37ab07174ed9c;p=dss.git Add the --kill subcommand. 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. --- diff --git a/dss.c b/dss.c index 01f1bc7..63f5f56 100644 --- 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 --- 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 --- 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 --- 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 --- 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);