From 52f740b87344f474ce15e0c9bb4a1ae800f57aac 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 1/1] 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 Conflicts: src/bin/lttng-sessiond/main.c src/common/utils.h --- src/bin/lttng-sessiond/main.c | 82 +++++++++++++++++++++++++++++++---- src/common/defaults.h | 1 + src/common/utils.c | 39 +++++++++++++++++ src/common/utils.h | 1 + 4 files changed, 115 insertions(+), 8 deletions(-) diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 5de918c27..841f5855a 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -79,6 +79,7 @@ static int opt_no_kernel; 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; @@ -458,6 +459,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 */ @@ -539,14 +561,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 */ @@ -578,6 +592,35 @@ static void cleanup(void) close_consumer_sockets(); + + /* + * 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", @@ -4514,6 +4557,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. */ @@ -4690,6 +4751,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 e81055a26..7f7c90580 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 unix socket path */ #define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/client-lttng-sessiond" diff --git a/src/common/utils.c b/src/common/utils.c index d4b42ea34..0d60dc251 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -467,6 +468,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 f08d2eb6b..8bb125a12 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -47,5 +47,6 @@ int utils_get_count_order_u32(uint32_t x); char *utils_get_home_dir(void); size_t utils_get_current_time_str(const char *format, char *dst, size_t len); gid_t utils_get_group_id(const char *name); +int utils_create_lock_file(const char *filepath); #endif /* _COMMON_UTILS_H */ -- 2.34.1