Tor 0.4.9.0-alpha-dev
lockfile.c
Go to the documentation of this file.
1/* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6/**
7 * \file lockfile.c
8 *
9 * \brief Implements lock files to prevent two Tor processes from using the
10 * same data directory at the same time.
11 **/
12
13#include "orconfig.h"
14#include "lib/fs/files.h"
15#include "lib/fs/lockfile.h"
16#include "lib/log/log.h"
17#include "lib/log/util_bug.h"
18#include "lib/malloc/malloc.h"
19
20#ifdef HAVE_SYS_FILE_H
21#include <sys/file.h>
22#endif
23#ifdef HAVE_FCNTL_H
24#include <fcntl.h>
25#endif
26#ifdef HAVE_UNISTD_H
27#include <unistd.h>
28#endif
29#ifdef _WIN32
30#include <windows.h>
31#include <sys/locking.h>
32#endif
33
34#include <errno.h>
35#include <string.h>
36
37/** Represents a lockfile on which we hold the lock. */
39 /** Name of the file */
40 char *filename;
41 /** File descriptor used to hold the file open */
42 int fd;
43};
44
45/** Try to get a lock on the lockfile <b>filename</b>, creating it as
46 * necessary. If someone else has the lock and <b>blocking</b> is true,
47 * wait until the lock is available. Otherwise return immediately whether
48 * we succeeded or not.
49 *
50 * Set *<b>locked_out</b> to true if somebody else had the lock, and to false
51 * otherwise.
52 *
53 * Return a <b>tor_lockfile_t</b> on success, NULL on failure.
54 *
55 * (Implementation note: because we need to fall back to fcntl on some
56 * platforms, these locks are per-process, not per-thread. If you want
57 * to do in-process locking, use tor_mutex_t like a normal person.
58 * On Windows, when <b>blocking</b> is true, the maximum time that
59 * is actually waited is 10 seconds, after which NULL is returned
60 * and <b>locked_out</b> is set to 1.)
61 */
63tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
64{
65 tor_lockfile_t *result;
66 int fd;
67 *locked_out = 0;
68
69 log_info(LD_FS, "Locking \"%s\"", filename);
70 fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
71 if (fd < 0) {
72 log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
73 strerror(errno));
74 return NULL;
75 }
76
77#ifdef _WIN32
78 _lseek(fd, 0, SEEK_SET);
79 if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) {
80 if (errno != EACCES && errno != EDEADLOCK)
81 log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
82 else
83 *locked_out = 1;
84 close(fd);
85 return NULL;
86 }
87#elif defined(HAVE_FLOCK)
88 if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
89 if (errno != EWOULDBLOCK)
90 log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
91 else
92 *locked_out = 1;
93 close(fd);
94 return NULL;
95 }
96#else
97 {
98 struct flock lock;
99 memset(&lock, 0, sizeof(lock));
100 lock.l_type = F_WRLCK;
101 lock.l_whence = SEEK_SET;
102 if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
103 if (errno != EACCES && errno != EAGAIN)
104 log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
105 else
106 *locked_out = 1;
107 close(fd);
108 return NULL;
109 }
110 }
111#endif /* defined(_WIN32) || ... */
112
113 result = tor_malloc(sizeof(tor_lockfile_t));
114 result->filename = tor_strdup(filename);
115 result->fd = fd;
116 return result;
117}
118
119/** Release the lock held as <b>lockfile</b>. */
120void
122{
124
125 log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
126#ifdef _WIN32
127 _lseek(lockfile->fd, 0, SEEK_SET);
128 if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
129 log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
130 strerror(errno));
131 }
132#elif defined(HAVE_FLOCK)
133 if (flock(lockfile->fd, LOCK_UN) < 0) {
134 log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
135 strerror(errno));
136 }
137#else
138 /* Closing the lockfile is sufficient. */
139#endif /* defined(_WIN32) || ... */
140
141 close(lockfile->fd);
142 lockfile->fd = -1;
145}
Wrappers for reading and writing data to files on disk.
int tor_open_cloexec(const char *path, int flags, unsigned mode)
Definition: files.c:54
tor_lockfile_t * tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
Definition: lockfile.c:63
void tor_lockfile_unlock(tor_lockfile_t *lockfile)
Definition: lockfile.c:121
Header for lockfile.c.
Headers for log.c.
#define LD_FS
Definition: log.h:70
static tor_lockfile_t * lockfile
Definition: main.c:653
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
char * filename
Definition: lockfile.c:40
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103