Fix: sessiond: freeze on channel creation on restart
[lttng-tools.git] / src / common / lockfile.c
1 /*
2 * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
3 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-only
6 *
7 */
8
9 #include <common/error.h>
10 #include <common/lockfile.h>
11 #include <common/macros.h>
12
13 #include <assert.h>
14
15 #include <fcntl.h>
16
17 #ifdef HAVE_FLOCK
18
19 #include <sys/file.h>
20
21 static int lock_file(const char *filepath, int fd)
22 {
23 int ret;
24
25 /*
26 * Attempt to lock the file. If this fails, there is
27 * already a process using the same lock file running
28 * and we should exit.
29 */
30 ret = flock(fd, LOCK_EX | LOCK_NB);
31 if (ret == -1) {
32 /* EWOULDBLOCK are expected if the file is locked: don't spam the logs. */
33 if (errno != EWOULDBLOCK) {
34 PERROR("Failed to apply lock on lock file: file_path=`%s`", filepath);
35 }
36 }
37
38 return ret;
39 }
40
41 #else /* HAVE_FLOCK */
42
43 static int lock_file(const char *filepath, int fd)
44 {
45 int ret;
46 struct flock lock = {};
47
48 lock.l_whence = SEEK_SET;
49 lock.l_type = F_WRLCK;
50
51 /*
52 * Attempt to lock the file. If this fails, there is
53 * already a process using the same lock file running
54 * and we should exit.
55 */
56 ret = fcntl(fd, F_SETLK, &lock);
57 if (ret == -1) {
58 /* EAGAIN and EACCESS are expected if the file is locked: don't spam the logs. */
59 if (errno != EAGAIN && errno != EACCES) {
60 PERROR("Failed to set lock on lock file: file_path=`%s`", filepath);
61 }
62 }
63
64 return ret;
65 }
66
67 #endif /* HAVE_FLOCK */
68
69 int utils_create_lock_file(const char *filepath)
70 {
71 int ret, fd;
72
73 assert(filepath);
74
75 fd = open(filepath, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
76 if (fd < 0) {
77 PERROR("Failed to open lock file `%s`", filepath);
78 fd = -1;
79 goto error;
80 }
81
82 /*
83 * Attempt to lock the file. If this fails, there is already a process using the same lock
84 * file running and we should exit.
85 *
86 * lock_file is chosen based on the build configuration, see implementations above.
87 */
88 ret = lock_file(filepath, fd);
89 if (ret == -1) {
90 ERR("Could not get lock file `%s`, another instance is running.", filepath);
91
92 if (close(fd)) {
93 PERROR("Failed to close lock file fd: fd=%d", fd);
94 }
95
96 fd = ret;
97 goto error;
98 }
99
100 DBG("Acquired lock file: file_path=`%s`", filepath);
101
102 error:
103 return fd;
104 }
This page took 0.036088 seconds and 4 git commands to generate.