Fix: Create a lock file to prevent multiple session daemons
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 14 Jul 2014 18:57:10 +0000 (14:57 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Mon, 14 Jul 2014 21:04:23 +0000 (17:04 -0400)
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 <jeremie.galarneau@efficios.com>
Signed-off-by: David Goulet <dgoulet@efficios.com>
Conflicts:
src/bin/lttng-sessiond/main.c
src/common/utils.h

src/bin/lttng-sessiond/main.c
src/common/defaults.h
src/common/utils.c
src/common/utils.h

index 5de918c27b6ab18207bb0aefe25bbb9ea606ce26..841f5855a5bfa5fa71a105c5359dd69b3c7ca026 100644 (file)
@@ -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);
+
        /* <fun> */
        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;
index e81055a265269d455ac366e17f2aa4b91346d187..7f7c9058062cabb70906aa903fb9fc61b84b5db0 100644 (file)
@@ -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"
index d4b42ea3491b22165fd9dc13c2c612782c3807db..0d60dc251c2e897969b604b79e57ee37b53a17bf 100644 (file)
@@ -29,6 +29,7 @@
 #include <inttypes.h>
 #include <grp.h>
 #include <pwd.h>
+#include <sys/file.h>
 
 #include <common/common.h>
 #include <common/runas.h>
@@ -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.
  *
index f08d2eb6b56f47f59743ca0fd315d84750dfbfcf..8bb125a1214e801ac513688f8395a0a15363d6b8 100644 (file)
@@ -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 */
This page took 0.030333 seconds and 4 git commands to generate.