diff options
Diffstat (limited to 'src/pathlocks.cc')
-rw-r--r-- | src/pathlocks.cc | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/src/pathlocks.cc b/src/pathlocks.cc index ff0226c84e5c..3ecbbbcbafd5 100644 --- a/src/pathlocks.cc +++ b/src/pathlocks.cc @@ -1,10 +1,39 @@ #include <cerrno> +#include <sys/types.h> +#include <sys/stat.h> #include <fcntl.h> #include "pathlocks.hh" +bool lockFile(int fd, LockType lockType, bool wait) +{ + struct flock lock; + if (lockType == ltRead) lock.l_type = F_RDLCK; + else if (lockType == ltWrite) lock.l_type = F_WRLCK; + else if (lockType == ltNone) lock.l_type = F_UNLCK; + else abort(); + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; /* entire file */ + + if (wait) { + while (fcntl(fd, F_SETLKW, &lock) != 0) + if (errno != EINTR) + throw SysError(format("acquiring/releasing lock")); + } else { + while (fcntl(fd, F_SETLK, &lock) != 0) { + if (errno == EACCES || errno == EAGAIN) return false; + if (errno != EINTR) + throw SysError(format("acquiring/releasing lock")); + } + } + + return true; +} + + /* This enables us to check whether are not already holding a lock on a file ourselves. POSIX locks (fcntl) suck in this respect: if we close a descriptor, the previous lock will be closed as well. And @@ -43,16 +72,8 @@ PathLocks::PathLocks(const PathSet & _paths) fds.push_back(fd); this->paths.push_back(lockPath); - /* Lock it. */ - struct flock lock; - lock.l_type = F_WRLCK; /* exclusive lock */ - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; /* entire file */ - - while (fcntl(fd, F_SETLKW, &lock) == -1) - if (errno != EINTR) - throw SysError(format("acquiring lock on `%1%'") % lockPath); + /* Acquire an exclusive lock. */ + lockFile(fd, ltWrite, true); lockedPaths.insert(lockPath); } |