aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/gc.cc10
-rw-r--r--src/libstore/local-store.cc12
-rw-r--r--src/libstore/local-store.hh2
3 files changed, 19 insertions, 5 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 2d7734729..ff66c3938 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -112,6 +112,9 @@ void LocalStore::addTempRoot(const StorePath & path)
}
+ if (!state->fdGCLock)
+ state->fdGCLock = openGCLock();
+
restart:
FdLock gcLock(state->fdGCLock.get(), ltRead, false, "");
@@ -653,8 +656,11 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
if (state.shouldDelete)
deletePath(reservedPath);
- /* Acquire the global GC root. */
- FdLock gcLock(_state.lock()->fdGCLock.get(), ltWrite, true, "waiting for the big garbage collector lock...");
+ /* Acquire the global GC root. Note: we don't use state->fdGCLock
+ here because then in auto-gc mode, another thread could
+ downgrade our exclusive lock. */
+ auto fdGCLock = openGCLock();
+ FdLock gcLock(fdGCLock.get(), ltWrite, true, "waiting for the big garbage collector lock...");
/* Start the server for receiving new roots. */
auto socketPath = stateDir.get() + gcSocketPath;
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index faecdb00b..0e6556e11 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -382,11 +382,16 @@ LocalStore::LocalStore(const Params & params)
(select id from Realisations where drvPath = ? and outputName = ?));
)");
}
+}
+
+AutoCloseFD LocalStore::openGCLock()
+{
Path fnGCLock = stateDir + "/gc.lock";
- state->fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
- if (!state->fdGCLock)
+ auto fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
+ if (!fdGCLock)
throw SysError("opening global GC lock '%1%'", fnGCLock);
+ return fdGCLock;
}
@@ -1509,7 +1514,8 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
/* Acquire the global GC lock to get a consistent snapshot of
existing and valid paths. */
- FdLock gcLock(_state.lock()->fdGCLock.get(), ltWrite, true, "waiting for the big garbage collector lock...");
+ auto fdGCLock = openGCLock();
+ FdLock gcLock(fdGCLock.get(), ltRead, true, "waiting for the big garbage collector lock...");
StringSet store;
for (auto & i : readDirectory(realStoreDir)) store.insert(i.name);
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 85c6c4495..12c057ec3 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -158,6 +158,8 @@ private:
void findTempRoots(Roots & roots, bool censor);
+ AutoCloseFD openGCLock();
+
public:
Roots findRoots(bool censor) override;