From 4ef4b5a2d21c914922c2f5fe09993240d2bd205f Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Mon, 14 Jul 2014 14:57:10 -0400 Subject: [PATCH] Fix: Create a lock file to prevent multiple session daemons MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit A lock file is used to ensure that only one session daemon per UID is running on the system. The lock file is created in the rundir. Signed-off-by: Jérémie Galarneau Signed-off-by: David Goulet --- src/bin/lttng-sessiond/main.c | 81 +++++++++++++++++++++++++++++++---- src/common/defaults.h | 1 + src/common/utils.c | 39 +++++++++++++++++ src/common/utils.h | 1 + 4 files changed, 114 insertions(+), 8 deletions(-) diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index cef104056..a8751c696 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -85,6 +85,7 @@ static char *opt_load_session_path; static pid_t ppid; /* Parent PID for --sig-parent option */ static pid_t child_ppid; /* Internal parent PID use with daemonize. */ static char *rundir; +static int lockfile_fd = -1; /* Set to 1 when a SIGUSR1 signal is received. */ static int recv_child_signal; @@ -511,6 +512,27 @@ static void close_consumer_sockets(void) } } +/* + * Generate the full lock file path using the rundir. + * + * Return the snprintf() return value thus a negative value is an error. + */ +static int generate_lock_file_path(char *path, size_t len) +{ + int ret; + + assert(path); + assert(rundir); + + /* Build lockfile path from rundir. */ + ret = snprintf(path, len, "%s/" DEFAULT_LTTNG_SESSIOND_LOCKFILE, rundir); + if (ret < 0) { + PERROR("snprintf lockfile path"); + } + + return ret; +} + /* * Cleanup the daemon */ @@ -592,14 +614,6 @@ static void cleanup(void) DBG("Removing directory %s", path); (void) rmdir(path); - /* - * We do NOT rmdir rundir because there are other processes - * using it, for instance lttng-relayd, which can start in - * parallel with this teardown. - */ - - free(rundir); - DBG("Cleaning up all sessions"); /* Destroy session list mutex */ @@ -664,6 +678,34 @@ static void cleanup(void) free(load_info); } + /* + * Cleanup lock file by deleting it and finaly closing it which will + * release the file system lock. + */ + if (lockfile_fd >= 0) { + char lockfile_path[PATH_MAX]; + + ret = generate_lock_file_path(lockfile_path, sizeof(lockfile_path)); + if (ret > 0) { + ret = remove(lockfile_path); + if (ret < 0) { + PERROR("remove lock file"); + } + ret = close(lockfile_fd); + if (ret < 0) { + PERROR("close lock file"); + } + } + } + + /* + * We do NOT rmdir rundir because there are other processes + * using it, for instance lttng-relayd, which can start in + * parallel with this teardown. + */ + + free(rundir); + /* */ DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm" "Matthew, BEET driven development works!%c[%dm", @@ -4854,6 +4896,24 @@ error: return; } +/* + * Create lockfile using the rundir and return its fd. + */ +static int create_lockfile(void) +{ + int ret; + char lockfile_path[PATH_MAX]; + + ret = generate_lock_file_path(lockfile_path, sizeof(lockfile_path)); + if (ret < 0) { + goto error; + } + + ret = utils_create_lock_file(lockfile_path); +error: + return ret; +} + /* * Write JUL TCP port using the rundir. */ @@ -5059,6 +5119,11 @@ int main(int argc, char **argv) } } + lockfile_fd = create_lockfile(); + if (lockfile_fd < 0) { + goto error; + } + /* Set consumer initial state */ kernel_consumerd_state = CONSUMER_STOPPED; ust_consumerd_state = CONSUMER_STOPPED; diff --git a/src/common/defaults.h b/src/common/defaults.h index 8107d973b..c857cb756 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -89,6 +89,7 @@ #define DEFAULT_LTTNG_HOME_RUNDIR "%s/.lttng" #define DEFAULT_LTTNG_SESSIOND_PIDFILE "lttng-sessiond.pid" #define DEFAULT_LTTNG_SESSIOND_JULPORT_FILE "jul.port" +#define DEFAULT_LTTNG_SESSIOND_LOCKFILE "lttng-sessiond.lck" /* Default probes list */ #define DEFAULT_LTTNG_KMOD_PROBES "LTTNG_KMOD_PROBES" diff --git a/src/common/utils.c b/src/common/utils.c index b640b950e..ff6d1c223 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -468,6 +469,44 @@ error: return ret; } +/* + * Create lock file to the given path and filename. + * Returns the associated file descriptor, -1 on error. + */ +LTTNG_HIDDEN +int utils_create_lock_file(const char *filepath) +{ + int ret; + int fd; + + assert(filepath); + + fd = open(filepath, O_CREAT, + O_WRONLY | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd < 0) { + PERROR("open lock file %s", filepath); + ret = -1; + goto error; + } + + /* + * Attempt to lock the file. If this fails, there is + * already a process using the same lock file running + * and we should exit. + */ + ret = flock(fd, LOCK_EX | LOCK_NB); + if (ret) { + WARN("Could not get lock file %s, another instance is running.", + filepath); + close(fd); + fd = ret; + goto error; + } + +error: + return fd; +} + /* * Recursively create directory using the given path and mode. * diff --git a/src/common/utils.h b/src/common/utils.h index cc80a5369..bdc0e14f0 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -52,5 +52,6 @@ size_t utils_get_current_time_str(const char *format, char *dst, size_t len); gid_t utils_get_group_id(const char *name); char *utils_generate_optstring(const struct option *long_options, size_t opt_count); +int utils_create_lock_file(const char *filepath); #endif /* _COMMON_UTILS_H */ -- 2.34.1