commit aa3edfd2053bb418907f204e171ae8f7e78c30eb Author: Nick Mathewson nickm@torproject.org Date: Thu Jun 28 11:33:50 2018 -0400
Move lockfile code into lib/fs --- src/common/compat.c | 111 ---------------------------------------- src/common/compat.h | 4 -- src/lib/fs/include.am | 2 + src/lib/fs/lockfile.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/fs/lockfile.h | 14 +++++ src/or/main.c | 1 + 6 files changed, 155 insertions(+), 115 deletions(-)
diff --git a/src/common/compat.c b/src/common/compat.c index 9fd966798..1199fdae9 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -131,116 +131,6 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt) #include "lib/net/address.h" #include "lib/sandbox/sandbox.h"
-/** Represents a lockfile on which we hold the lock. */ -struct tor_lockfile_t { - /** Name of the file */ - char *filename; - /** File descriptor used to hold the file open */ - int fd; -}; - -/** Try to get a lock on the lockfile <b>filename</b>, creating it as - * necessary. If someone else has the lock and <b>blocking</b> is true, - * wait until the lock is available. Otherwise return immediately whether - * we succeeded or not. - * - * Set *<b>locked_out</b> to true if somebody else had the lock, and to false - * otherwise. - * - * Return a <b>tor_lockfile_t</b> on success, NULL on failure. - * - * (Implementation note: because we need to fall back to fcntl on some - * platforms, these locks are per-process, not per-thread. If you want - * to do in-process locking, use tor_mutex_t like a normal person. - * On Windows, when <b>blocking</b> is true, the maximum time that - * is actually waited is 10 seconds, after which NULL is returned - * and <b>locked_out</b> is set to 1.) - */ -tor_lockfile_t * -tor_lockfile_lock(const char *filename, int blocking, int *locked_out) -{ - tor_lockfile_t *result; - int fd; - *locked_out = 0; - - log_info(LD_FS, "Locking "%s"", filename); - fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600); - if (fd < 0) { - log_warn(LD_FS,"Couldn't open "%s" for locking: %s", filename, - strerror(errno)); - return NULL; - } - -#ifdef _WIN32 - _lseek(fd, 0, SEEK_SET); - if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) { - if (errno != EACCES && errno != EDEADLOCK) - log_warn(LD_FS,"Couldn't lock "%s": %s", filename, strerror(errno)); - else - *locked_out = 1; - close(fd); - return NULL; - } -#elif defined(HAVE_FLOCK) - if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) { - if (errno != EWOULDBLOCK) - log_warn(LD_FS,"Couldn't lock "%s": %s", filename, strerror(errno)); - else - *locked_out = 1; - close(fd); - return NULL; - } -#else - { - struct flock lock; - memset(&lock, 0, sizeof(lock)); - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) { - if (errno != EACCES && errno != EAGAIN) - log_warn(LD_FS, "Couldn't lock "%s": %s", filename, strerror(errno)); - else - *locked_out = 1; - close(fd); - return NULL; - } - } -#endif /* defined(_WIN32) || ... */ - - result = tor_malloc(sizeof(tor_lockfile_t)); - result->filename = tor_strdup(filename); - result->fd = fd; - return result; -} - -/** Release the lock held as <b>lockfile</b>. */ -void -tor_lockfile_unlock(tor_lockfile_t *lockfile) -{ - tor_assert(lockfile); - - log_info(LD_FS, "Unlocking "%s"", lockfile->filename); -#ifdef _WIN32 - _lseek(lockfile->fd, 0, SEEK_SET); - if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) { - log_warn(LD_FS,"Error unlocking "%s": %s", lockfile->filename, - strerror(errno)); - } -#elif defined(HAVE_FLOCK) - if (flock(lockfile->fd, LOCK_UN) < 0) { - log_warn(LD_FS, "Error unlocking "%s": %s", lockfile->filename, - strerror(errno)); - } -#else - /* Closing the lockfile is sufficient. */ -#endif /* defined(_WIN32) || ... */ - - close(lockfile->fd); - lockfile->fd = -1; - tor_free(lockfile->filename); - tor_free(lockfile); -} - /** Number of extra file descriptors to keep in reserve beyond those that we * tell Tor it's allowed to use. */ #define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */ @@ -550,7 +440,6 @@ compute_num_cpus(void) return num_cpus; }
- /** Called before we make any calls to network-related functions. * (Some operating systems require their network libraries to be * initialized.) */ diff --git a/src/common/compat.h b/src/common/compat.h index 018caab24..e455dc8ef 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -108,10 +108,6 @@ #endif /* !defined(timercmp) */
/* ===== File compatibility */ -typedef struct tor_lockfile_t tor_lockfile_t; -tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking, - int *locked_out); -void tor_lockfile_unlock(tor_lockfile_t *lockfile);
/* ===== Net compatibility */
diff --git a/src/lib/fs/include.am b/src/lib/fs/include.am index dcfd0b201..0256c0f2f 100644 --- a/src/lib/fs/include.am +++ b/src/lib/fs/include.am @@ -9,6 +9,7 @@ src_lib_libtor_fs_a_SOURCES = \ src/lib/fs/conffile.c \ src/lib/fs/dir.c \ src/lib/fs/files.c \ + src/lib/fs/lockfile.c \ src/lib/fs/mmap.c \ src/lib/fs/path.c \ src/lib/fs/storagedir.c \ @@ -23,6 +24,7 @@ noinst_HEADERS += \ src/lib/fs/conffile.h \ src/lib/fs/dir.h \ src/lib/fs/files.h \ + src/lib/fs/lockfile.h \ src/lib/fs/mmap.h \ src/lib/fs/path.h \ src/lib/fs/storagedir.h \ diff --git a/src/lib/fs/lockfile.c b/src/lib/fs/lockfile.c new file mode 100644 index 000000000..3fc9cd426 --- /dev/null +++ b/src/lib/fs/lockfile.c @@ -0,0 +1,138 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "lib/fs/files.h" +#include "lib/fs/lockfile.h" +#include "lib/log/torlog.h" +#include "lib/log/util_bug.h" +#include "lib/malloc/util_malloc.h" + +#ifdef HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef _WIN32 +#include <windows.h> +#include <sys/locking.h> +#endif + +#include <errno.h> +#include <string.h> + +/** Represents a lockfile on which we hold the lock. */ +struct tor_lockfile_t { + /** Name of the file */ + char *filename; + /** File descriptor used to hold the file open */ + int fd; +}; + +/** Try to get a lock on the lockfile <b>filename</b>, creating it as + * necessary. If someone else has the lock and <b>blocking</b> is true, + * wait until the lock is available. Otherwise return immediately whether + * we succeeded or not. + * + * Set *<b>locked_out</b> to true if somebody else had the lock, and to false + * otherwise. + * + * Return a <b>tor_lockfile_t</b> on success, NULL on failure. + * + * (Implementation note: because we need to fall back to fcntl on some + * platforms, these locks are per-process, not per-thread. If you want + * to do in-process locking, use tor_mutex_t like a normal person. + * On Windows, when <b>blocking</b> is true, the maximum time that + * is actually waited is 10 seconds, after which NULL is returned + * and <b>locked_out</b> is set to 1.) + */ +tor_lockfile_t * +tor_lockfile_lock(const char *filename, int blocking, int *locked_out) +{ + tor_lockfile_t *result; + int fd; + *locked_out = 0; + + log_info(LD_FS, "Locking "%s"", filename); + fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600); + if (fd < 0) { + log_warn(LD_FS,"Couldn't open "%s" for locking: %s", filename, + strerror(errno)); + return NULL; + } + +#ifdef _WIN32 + _lseek(fd, 0, SEEK_SET); + if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) { + if (errno != EACCES && errno != EDEADLOCK) + log_warn(LD_FS,"Couldn't lock "%s": %s", filename, strerror(errno)); + else + *locked_out = 1; + close(fd); + return NULL; + } +#elif defined(HAVE_FLOCK) + if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) { + if (errno != EWOULDBLOCK) + log_warn(LD_FS,"Couldn't lock "%s": %s", filename, strerror(errno)); + else + *locked_out = 1; + close(fd); + return NULL; + } +#else + { + struct flock lock; + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) { + if (errno != EACCES && errno != EAGAIN) + log_warn(LD_FS, "Couldn't lock "%s": %s", filename, strerror(errno)); + else + *locked_out = 1; + close(fd); + return NULL; + } + } +#endif /* defined(_WIN32) || ... */ + + result = tor_malloc(sizeof(tor_lockfile_t)); + result->filename = tor_strdup(filename); + result->fd = fd; + return result; +} + +/** Release the lock held as <b>lockfile</b>. */ +void +tor_lockfile_unlock(tor_lockfile_t *lockfile) +{ + tor_assert(lockfile); + + log_info(LD_FS, "Unlocking "%s"", lockfile->filename); +#ifdef _WIN32 + _lseek(lockfile->fd, 0, SEEK_SET); + if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) { + log_warn(LD_FS,"Error unlocking "%s": %s", lockfile->filename, + strerror(errno)); + } +#elif defined(HAVE_FLOCK) + if (flock(lockfile->fd, LOCK_UN) < 0) { + log_warn(LD_FS, "Error unlocking "%s": %s", lockfile->filename, + strerror(errno)); + } +#else + /* Closing the lockfile is sufficient. */ +#endif /* defined(_WIN32) || ... */ + + close(lockfile->fd); + lockfile->fd = -1; + tor_free(lockfile->filename); + tor_free(lockfile); +} diff --git a/src/lib/fs/lockfile.h b/src/lib/fs/lockfile.h new file mode 100644 index 000000000..1c5bb023b --- /dev/null +++ b/src/lib/fs/lockfile.h @@ -0,0 +1,14 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_LOCKFILE_H +#define TOR_LOCKFILE_H + +typedef struct tor_lockfile_t tor_lockfile_t; +tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking, + int *locked_out); +void tor_lockfile_unlock(tor_lockfile_t *lockfile); + +#endif diff --git a/src/or/main.c b/src/or/main.c index 50e51915b..0ba38658a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -112,6 +112,7 @@ #include "or/ext_orport.h" #include "lib/memarea/memarea.h" #include "lib/sandbox/sandbox.h" +#include "lib/fs/lockfile.h"
#include <event2/event.h>
tor-commits@lists.torproject.org