diff --git a/lix/legacy/nix-store.cc b/lix/legacy/nix-store.cc index 1c885f1a6..b0d42e2d5 100644 --- a/lix/legacy/nix-store.cc +++ b/lix/legacy/nix-store.cc @@ -888,7 +888,7 @@ static void opServe(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) auto paths = ServeProto::Serialise::read(*store, rconn); if (lock && writeAllowed) for (auto & path : paths) - store->addTempRoot(path); + aio.blockOn(store->addTempRoot(path)); if (substitute && writeAllowed) { aio.blockOn(store->substitutePaths(paths)); diff --git a/lix/legacy/user-env.cc b/lix/legacy/user-env.cc index f061137d4..74ceed2e4 100644 --- a/lix/legacy/user-env.cc +++ b/lix/legacy/user-env.cc @@ -66,7 +66,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, /* This is only necessary when installing store paths, e.g., `nix-env -i /nix/store/abcd...-foo'. */ - state.ctx.store->addTempRoot(*j.second); + state.aio.blockOn(state.ctx.store->addTempRoot(*j.second)); state.aio.blockOn(state.ctx.store->ensurePath(*j.second)); references.insert(*j.second); diff --git a/lix/libfetchers/cache.cc b/lix/libfetchers/cache.cc index b225928bf..8b8773be9 100644 --- a/lix/libfetchers/cache.cc +++ b/lix/libfetchers/cache.cc @@ -108,7 +108,7 @@ struct CacheImpl : Cache auto locked = stmt.getInt(2) != 0; auto timestamp = stmt.getInt(3); - store->addTempRoot(storePath); + TRY_AWAIT(store->addTempRoot(storePath)); if (!store->isValidPath(storePath)) { // FIXME: we could try to substitute 'storePath'. debug("ignoring disappeared cache entry '%s'", inAttrsJSON); diff --git a/lix/libfetchers/path.cc b/lix/libfetchers/path.cc index e46f32ec1..4a33d2c72 100644 --- a/lix/libfetchers/path.cc +++ b/lix/libfetchers/path.cc @@ -127,7 +127,7 @@ struct PathInputScheme : InputScheme auto storePath = store->maybeParseStorePath(absPath); if (storePath) - store->addTempRoot(*storePath); + TRY_AWAIT(store->addTempRoot(*storePath)); time_t mtime = 0; if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) { diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index 87f9a1b2c..bd5bd9461 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -185,17 +185,17 @@ try { trace("loading derivation"); if (nrFailed != 0) { - return {done( + co_return done( BuildResult::MiscFailure, {}, Error("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath)) - )}; + ); } /* `drvPath' should already be a root, but let's be on the safe side: if the user forgot to make it a root, we wouldn't want things being garbage collected while we're busy. */ - worker.evalStore.addTempRoot(drvPath); + TRY_AWAIT(worker.evalStore.addTempRoot(drvPath)); /* Get the derivation. It is probably in the eval store, but it might be inthe main store: @@ -211,9 +211,9 @@ try { } assert(drv); - return haveDerivation(); + co_return TRY_AWAIT(haveDerivation()); } catch (...) { - return {result::current_exception()}; + co_return result::current_exception(); } @@ -250,7 +250,7 @@ try { for (auto & i : drv->outputsAndOptPaths(worker.store)) if (i.second.second) - worker.store.addTempRoot(*i.second.second); + TRY_AWAIT(worker.store.addTempRoot(*i.second.second)); auto outputHashes = staticOutputHashes(worker.evalStore, *drv); for (auto & [outputName, outputHash] : outputHashes) diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index 2ddcb5144..0e9106681 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -1185,8 +1185,8 @@ struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStor ) override try { unsupported("buildDerivation"); } catch (...) { return {result::current_exception()}; } - void addTempRoot(const StorePath & path) override - { } + kj::Promise> addTempRoot(const StorePath & path) override + { return {result::success()}; } void addIndirectRoot(const Path & path) override { } diff --git a/lix/libstore/build/substitution-goal.cc b/lix/libstore/build/substitution-goal.cc index 34f5294af..4eecf9f5b 100644 --- a/lix/libstore/build/substitution-goal.cc +++ b/lix/libstore/build/substitution-goal.cc @@ -52,7 +52,7 @@ kj::Promise> PathSubstitutionGoal::workImpl() noexcept try { trace("init"); - worker.store.addTempRoot(storePath); + TRY_AWAIT(worker.store.addTempRoot(storePath)); /* If the path already exists we're done. */ if (!repair && worker.store.isValidPath(storePath)) { diff --git a/lix/libstore/build/worker.cc b/lix/libstore/build/worker.cc index f38e6cb6a..8742c63de 100644 --- a/lix/libstore/build/worker.cc +++ b/lix/libstore/build/worker.cc @@ -1,3 +1,4 @@ +#include "build/derivation-goal.hh" #include "lix/libutil/async-collect.hh" #include "lix/libutil/charptr-cast.hh" #include "lix/libstore/build/worker.hh" @@ -146,7 +147,7 @@ Worker::makeBasicDerivationGoal( try { /* Prevent the .chroot directory from being garbage-collected. (See isActiveTempFile() in gc.cc.) */ - store.addTempRoot(drvPath); + TRY_AWAIT(store.addTempRoot(drvPath)); co_return makeGoalCommon( derivationGoals, diff --git a/lix/libstore/daemon.cc b/lix/libstore/daemon.cc index c56e0e884..05037c921 100644 --- a/lix/libstore/daemon.cc +++ b/lix/libstore/daemon.cc @@ -666,7 +666,7 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref store case WorkerProto::Op::AddTempRoot: { auto path = store->parseStorePath(readString(from)); logger->startWork(); - store->addTempRoot(path); + aio.blockOn(store->addTempRoot(path)); logger->stopWork(); to << 1; break; diff --git a/lix/libstore/gc.cc b/lix/libstore/gc.cc index ab118258f..b09015492 100644 --- a/lix/libstore/gc.cc +++ b/lix/libstore/gc.cc @@ -2,6 +2,7 @@ #include "lix/libstore/local-store.hh" #include "lix/libstore/pathlocks.hh" #include "lix/libutil/processes.hh" +#include "lix/libutil/result.hh" #include "lix/libutil/signals.hh" #include "lix/libutil/finally.hh" #include "lix/libutil/unix-domain-socket.hh" @@ -65,7 +66,7 @@ try { running. This should be superfluous since the caller should have registered this root yet, but let's be on the safe side. */ - addTempRoot(storePath); + TRY_AWAIT(addTempRoot(storePath)); /* Don't clobber the link if it already exists and doesn't point to the Nix store. */ @@ -116,27 +117,28 @@ void LocalStore::createTempRootsFile() } -void LocalStore::addTempRoot(const StorePath & path) -{ +kj::Promise> LocalStore::addTempRoot(const StorePath & path) +try { if (config().readOnly) { debug("Read-only store doesn't support creating lock files for temp roots, but nothing can be deleted anyways."); - return; + co_return result::success(); } createTempRootsFile(); /* Open/create the global GC lock file. */ - { + auto & fdGCLock = [&]() -> auto & { auto fdGCLock(_fdGCLock.lock()); if (!*fdGCLock) *fdGCLock = openGCLock(); - } + return *fdGCLock; + }(); restart: /* Try to acquire a shared global GC lock (non-blocking). This only succeeds if the garbage collector is not currently running. */ - FdLock gcLock(*_fdGCLock.lock(), ltRead, FdLock::dont_wait); + FdLock gcLock(fdGCLock, ltRead, FdLock::dont_wait); if (!gcLock.valid()) { /* We couldn't get a shared global GC lock, so the garbage @@ -190,6 +192,9 @@ void LocalStore::addTempRoot(const StorePath & path) seen by a future run of the garbage collector. */ auto s = printStorePath(path) + '\0'; writeFull(_fdTempRoots.lock()->get(), s); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } diff --git a/lix/libstore/local-store.cc b/lix/libstore/local-store.cc index 9e06b7117..3ce6c237d 100644 --- a/lix/libstore/local-store.cc +++ b/lix/libstore/local-store.cc @@ -1214,7 +1214,7 @@ try { } }; - addTempRoot(info.path); + TRY_AWAIT(addTempRoot(info.path)); if (repair || !isValidPath(info.path)) { @@ -1366,7 +1366,7 @@ try { auto dstPath = makeFixedOutputPathFromCA(name, desc); - addTempRoot(dstPath); + TRY_AWAIT(addTempRoot(dstPath)); if (repair || !isValidPath(dstPath)) { @@ -1436,7 +1436,7 @@ try { .references = references, }); - addTempRoot(dstPath); + TRY_AWAIT(addTempRoot(dstPath)); if (repair || !isValidPath(dstPath)) { diff --git a/lix/libstore/local-store.hh b/lix/libstore/local-store.hh index 66263fe15..9d7c7401a 100644 --- a/lix/libstore/local-store.hh +++ b/lix/libstore/local-store.hh @@ -218,7 +218,7 @@ public: const StorePathSet & references, RepairFlag repair) override; - void addTempRoot(const StorePath & path) override; + kj::Promise> addTempRoot(const StorePath & path) override; private: diff --git a/lix/libstore/optimise-store.cc b/lix/libstore/optimise-store.cc index 541114f52..639cec6d9 100644 --- a/lix/libstore/optimise-store.cc +++ b/lix/libstore/optimise-store.cc @@ -269,7 +269,7 @@ try { uint64_t done = 0; for (auto & i : paths) { - addTempRoot(i); + TRY_AWAIT(addTempRoot(i)); if (!isValidPath(i)) continue; /* path was GC'ed, probably */ { Activity act(*logger, lvlTalkative, actUnknown, fmt("optimising path '%s'", printStorePath(i))); diff --git a/lix/libstore/remote-store.cc b/lix/libstore/remote-store.cc index 7cbff236f..034581d7e 100644 --- a/lix/libstore/remote-store.cc +++ b/lix/libstore/remote-store.cc @@ -758,12 +758,15 @@ try { } -void RemoteStore::addTempRoot(const StorePath & path) -{ +kj::Promise> RemoteStore::addTempRoot(const StorePath & path) +try { auto conn(getConnection()); conn->to << WorkerProto::Op::AddTempRoot << printStorePath(path); conn.processStderr(); readInt(conn->from); + return {result::success()}; +} catch (...) { + return {result::current_exception()}; } diff --git a/lix/libstore/remote-store.hh b/lix/libstore/remote-store.hh index 0c26f3fc9..fdb13bf5c 100644 --- a/lix/libstore/remote-store.hh +++ b/lix/libstore/remote-store.hh @@ -129,7 +129,7 @@ public: kj::Promise> ensurePath(const StorePath & path) override; - void addTempRoot(const StorePath & path) override; + kj::Promise> addTempRoot(const StorePath & path) override; Roots findRoots(bool censor) override; diff --git a/lix/libstore/store-api.hh b/lix/libstore/store-api.hh index b059f0c78..14b7bb98c 100644 --- a/lix/libstore/store-api.hh +++ b/lix/libstore/store-api.hh @@ -666,8 +666,13 @@ public: * Add a store path as a temporary root of the garbage collector. * The root disappears as soon as we exit. */ - virtual void addTempRoot(const StorePath & path) - { debug("not creating temporary root, store doesn't support GC"); } + virtual kj::Promise> addTempRoot(const StorePath & path) + try { + debug("not creating temporary root, store doesn't support GC"); + return {result::success()}; + } catch (...) { + return {result::current_exception()}; + } /** * @return a string representing information about the path that diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs index 65d0b93db..b8406a8bd 100644 --- a/perl/lib/Nix/Store.xs +++ b/perl/lib/Nix/Store.xs @@ -368,7 +368,7 @@ SV * derivationFromPath(char * drvPath) void addTempRoot(char * storePath) PPCODE: try { - store()->addTempRoot(store()->parseStorePath(storePath)); + aio().blockOn(store()->addTempRoot(store()->parseStorePath(storePath))); } catch (Error & e) { croak("%s", e.what()); }