aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/gc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/gc.cc')
-rw-r--r--src/libstore/gc.cc26
1 files changed, 26 insertions, 0 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