mkdir munmap putenv realpath rmdir socket strchr strcspn strdup \
strncasecmp strndup strnlen strpbrk strrchr strstr strtol strtoul \
strtoull dirfd gethostbyname2 getipnodebyname epoll_create1 \
- sched_getcpu sysconf sync_file_range getrandom
+ sched_getcpu sysconf sync_file_range getrandom flock
])
# Check if clock_gettime, timer_create, timer_settime, and timer_delete are available in lib rt, and if so,
#include <assert.h>
+#include <fcntl.h>
+
#ifdef HAVE_FLOCK
+#include <sys/file.h>
+
+static int lock_file(const char *filepath, int fd)
+{
+ int ret;
+
+ /*
+ * 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 == -1) {
+ /* EWOULDBLOCK are expected if the file is locked: don't spam the logs. */
+ if (errno != EWOULDBLOCK) {
+ PERROR("Failed to apply lock on lock file: file_path=`%s`", filepath);
+ }
+ }
+
+ return ret;
+}
+
#else /* HAVE_FLOCK */
-#include <fcntl.h>
+static int lock_file(const char *filepath, int fd)
+{
+ int ret;
+ struct flock lock = {};
+
+ lock.l_whence = SEEK_SET;
+ lock.l_type = F_WRLCK;
+
+ /*
+ * Attempt to lock the file. If this fails, there is
+ * already a process using the same lock file running
+ * and we should exit.
+ */
+ ret = fcntl(fd, F_SETLK, &lock);
+ if (ret == -1) {
+ /* EAGAIN and EACCESS are expected if the file is locked: don't spam the logs. */
+ if (errno != EAGAIN && errno != EACCES) {
+ PERROR("Failed to set lock on lock file: file_path=`%s`", filepath);
+ }
+ }
+
+ return ret;
+}
+
+#endif /* HAVE_FLOCK */
int utils_create_lock_file(const char *filepath)
{
- int ret;
- int fd;
- struct flock lock;
+ int ret, fd;
assert(filepath);
- memset(&lock, 0, sizeof(lock));
fd = open(filepath, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (fd < 0) {
- PERROR("open lock file %s", filepath);
+ PERROR("Failed to open lock file `%s`", filepath);
fd = -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.
+ * Attempt to lock the file. If this fails, there is already a process using the same lock
+ * file running and we should exit.
+ *
+ * lock_file is chosen based on the build configuration, see implementations above.
*/
- lock.l_whence = SEEK_SET;
- lock.l_type = F_WRLCK;
-
- ret = fcntl(fd, F_SETLK, &lock);
+ ret = lock_file(filepath, fd);
if (ret == -1) {
- PERROR("fcntl lock file");
- ERR("Could not get lock file %s, another instance is running.", filepath);
+ ERR("Could not get lock file `%s`, another instance is running.", filepath);
+
if (close(fd)) {
- PERROR("close lock file");
+ PERROR("Failed to close lock file fd: fd=%d", fd);
}
+
fd = ret;
goto error;
}
+ DBG("Acquired lock file: file_path=`%s`", filepath);
+
error:
return fd;
}
-
-#endif /* HAVE_FLOCK */