about summary refs log tree commit diff
path: root/src/pathlocks.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/pathlocks.cc')
-rw-r--r--src/pathlocks.cc41
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);
     }