aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-01-31 12:19:53 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-01-31 12:19:53 +0000
commit33c5d23b814e16687808d5f2d79798fef7dc2a8a (patch)
treefe7f49222ff8f4e622cb6dfb5440ff22d888f186 /src/libstore
parent1328aa33077fd1cf84869e366c82b8ea1d1abb5d (diff)
* Don't delete active lock files.
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/gc.cc26
-rw-r--r--src/libstore/gc.hh4
-rw-r--r--src/libstore/pathlocks.cc5
3 files changed, 31 insertions, 4 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 4c6a944b8..e7321449e 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -194,9 +194,35 @@ void collectGarbage(const PathSet & roots, GCAction action,
debug(format("dead path `%1%'") % path);
result.insert(path);
+ AutoCloseFD fdLock;
+
if (action == gcDeleteDead) {
printMsg(lvlInfo, format("deleting `%1%'") % path);
+
+ /* Only delete a lock file if we can acquire a write lock
+ on it. That means that it's either stale, or the
+ process that created it hasn't locked it yet. In the
+ latter case the other process will detect that we
+ deleted the lock, and retry (see pathlocks.cc). */
+ if (path.size() >= 5 && string(path, path.size() - 5) == ".lock") {
+
+ fdLock = open(path.c_str(), O_RDWR);
+ if (fdLock == -1) {
+ if (errno == ENOENT) continue;
+ throw SysError(format("opening lock file `%1%'") % path);
+ }
+
+ if (!lockFile(fdLock, ltWrite, false)) {
+ debug(format("skipping active lock `%1%'") % path);
+ continue;
+ }
+ }
+
deleteFromStore(path);
+
+ if (fdLock != -1)
+ /* Write token to stale (deleted) lock file. */
+ writeFull(fdLock, (const unsigned char *) "d", 1);
}
/* Only delete lock files if the path is belongs to doesn't
diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh
index 838188ade..c8f908b15 100644
--- a/src/libstore/gc.hh
+++ b/src/libstore/gc.hh
@@ -16,7 +16,9 @@ void collectGarbage(const PathSet & roots, GCAction action,
PathSet & result);
/* Register a temporary GC root. This root will automatically
- disappear when this process exits. */
+ disappear when this process exits. WARNING: this function should
+ not be called inside a BDB transaction, otherwise we can
+ deadlock. */
void addTempRoot(const Path & path);
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index a92b2225a..3beb49aac 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -127,9 +127,8 @@ PathLocks::~PathLocks()
/* Write a (meaningless) token to the file to indicate to
other processes waiting on this lock that the lock is
stale (deleted). */
- if (write(i->first, "d", 1) == 1) {
- unlink(i->second.c_str());
- }
+ unlink(i->second.c_str());
+ writeFull(i->first, (const unsigned char *) "d", 1);
/* Note that the result of unlink() is ignored; removing
the lock file is an optimisation, not a necessity. */
}