diff options
-rw-r--r-- | src/libstore/gc.cc | 10 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 12 | ||||
-rw-r--r-- | src/libstore/local-store.hh | 2 |
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; |