aboutsummaryrefslogtreecommitdiff
path: root/src/pathlocks.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-08-01 14:11:19 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-08-01 14:11:19 +0000
commit545145cd582cd80b857760ec11bb5a91b6271506 (patch)
treee992edea7a634ed268ac10444add5dcfac6a4f05 /src/pathlocks.cc
parent9df93f30bda81ffa3cf040c146347e02d3a56666 (diff)
* normaliseFState() now locks all output paths prior to building, thus
ensuring that simultaneous invocations of Nix don't clobber each other's builds. * Fixed a bug in `make install'.
Diffstat (limited to 'src/pathlocks.cc')
-rw-r--r--src/pathlocks.cc48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/pathlocks.cc b/src/pathlocks.cc
new file mode 100644
index 000000000..ac53dc643
--- /dev/null
+++ b/src/pathlocks.cc
@@ -0,0 +1,48 @@
+#include <fcntl.h>
+
+#include "pathlocks.hh"
+
+
+PathLocks::PathLocks(const Strings & _paths)
+{
+ /* Note that `fds' is built incrementally so that the destructor
+ will only release those locks that we have already acquired. */
+
+ /* Sort the paths. This assures that locks are always acquired in
+ the same order, thus preventing deadlocks. */
+ Strings paths(_paths);
+ paths.sort();
+
+ /* Acquire the lock for each path. */
+ for (Strings::iterator i = paths.begin(); i != paths.end(); i++) {
+ string path = *i;
+ string lockPath = path + ".lock";
+
+ debug(format("locking path `%1%'") % path);
+
+ /* Open/create the lock file. */
+ int fd = open(lockPath.c_str(), O_WRONLY | O_CREAT, 0666);
+ if (fd == -1)
+ throw SysError(format("opening lock file `%1%'") % lockPath);
+
+ fds.push_back(fd);
+
+ /* 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);
+ }
+}
+
+
+PathLocks::~PathLocks()
+{
+ for (list<int>::iterator i = fds.begin(); i != fds.end(); i++)
+ close(*i);
+}