diff --git a/lix/libstore/binary-cache-store.cc b/lix/libstore/binary-cache-store.cc index 7b97cc181..d61cc7cee 100644 --- a/lix/libstore/binary-cache-store.cc +++ b/lix/libstore/binary-cache-store.cc @@ -521,8 +521,9 @@ ref BinaryCacheStore::getFSAccessor() return make_ref(ref(shared_from_this()), config().localNarCache); } -void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSet & sigs) -{ +kj::Promise> +BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSet & sigs) +try { /* Note: this is inherently racy since there is no locking on binary caches. In particular, with S3 this unreliable, even when addSignatures() is called sequentially on a path, because @@ -534,6 +535,9 @@ void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSe narInfo->sigs.insert(sigs.begin(), sigs.end()); writeNarInfo(narInfo); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } kj::Promise>> diff --git a/lix/libstore/binary-cache-store.hh b/lix/libstore/binary-cache-store.hh index ea22c9a3a..36f2106de 100644 --- a/lix/libstore/binary-cache-store.hh +++ b/lix/libstore/binary-cache-store.hh @@ -153,7 +153,8 @@ public: ref getFSAccessor() override; - void addSignatures(const StorePath & storePath, const StringSet & sigs) override; + kj::Promise> + addSignatures(const StorePath & storePath, const StringSet & sigs) override; kj::Promise>> getBuildLogExact(const StorePath & path) override; diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index bdb85d669..57a82fb73 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -1242,8 +1242,9 @@ struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStor return {result::success()}; } - void addSignatures(const StorePath & storePath, const StringSet & sigs) override - { unsupported("addSignatures"); } + kj::Promise> + addSignatures(const StorePath & storePath, const StringSet & sigs) override + try { unsupported("addSignatures"); } catch (...) { return {result::current_exception()}; } kj::Promise> queryMissing(const std::vector & targets, StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, diff --git a/lix/libstore/daemon.cc b/lix/libstore/daemon.cc index f90d63704..5a9cadf08 100644 --- a/lix/libstore/daemon.cc +++ b/lix/libstore/daemon.cc @@ -875,7 +875,7 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref store auto path = store->parseStorePath(readString(from)); StringSet sigs = readStrings(from); logger->startWork(); - store->addSignatures(path, sigs); + aio.blockOn(store->addSignatures(path, sigs)); logger->stopWork(); to << 1; break; diff --git a/lix/libstore/local-store.cc b/lix/libstore/local-store.cc index b0538d085..117029003 100644 --- a/lix/libstore/local-store.cc +++ b/lix/libstore/local-store.cc @@ -1810,21 +1810,31 @@ kj::Promise>> LocalStore::isTrustedClient() } -void LocalStore::addSignatures(const StorePath & storePath, const StringSet & sigs) -{ - retrySQLite([&]() { - auto state = dbPool.get(); +kj::Promise> +LocalStore::addSignatures(const StorePath & storePath, const StringSet & sigs) +try { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + TRY_AWAIT(retrySQLite([&]() -> kj::Promise> { + try { + auto state = dbPool.get(); - SQLiteTxn txn = state->db.beginTransaction(SQLiteTxnType::Immediate); + SQLiteTxn txn = state->db.beginTransaction(SQLiteTxnType::Immediate); - auto info = std::const_pointer_cast(queryPathInfoInternal(*state, storePath)); + auto info = std::const_pointer_cast(queryPathInfoInternal(*state, storePath)); - info->sigs.insert(sigs.begin(), sigs.end()); + info->sigs.insert(sigs.begin(), sigs.end()); - updatePathInfo(*state, *info); + updatePathInfo(*state, *info); - txn.commit(); - }, always_progresses); + txn.commit(); + co_return result::success(); + } catch (...) { + co_return result::current_exception(); + } + })); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } diff --git a/lix/libstore/local-store.hh b/lix/libstore/local-store.hh index 2cdee0f0f..715da3130 100644 --- a/lix/libstore/local-store.hh +++ b/lix/libstore/local-store.hh @@ -307,7 +307,8 @@ public: kj::Promise>> isTrustedClient() override; - void addSignatures(const StorePath & storePath, const StringSet & sigs) override; + kj::Promise> + addSignatures(const StorePath & storePath, const StringSet & sigs) override; /** * If free disk space in /nix/store if below minFree, delete diff --git a/lix/libstore/remote-store.cc b/lix/libstore/remote-store.cc index ef5c1bb2d..aa6f1d47a 100644 --- a/lix/libstore/remote-store.cc +++ b/lix/libstore/remote-store.cc @@ -896,12 +896,16 @@ try { } -void RemoteStore::addSignatures(const StorePath & storePath, const StringSet & sigs) -{ +kj::Promise> +RemoteStore::addSignatures(const StorePath & storePath, const StringSet & sigs) +try { auto conn(getConnection()); conn->to << WorkerProto::Op::AddSignatures << printStorePath(storePath) << sigs; conn.processStderr(); readInt(conn->from); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } diff --git a/lix/libstore/remote-store.hh b/lix/libstore/remote-store.hh index c5d12028e..1f23cb366 100644 --- a/lix/libstore/remote-store.hh +++ b/lix/libstore/remote-store.hh @@ -156,7 +156,8 @@ public: kj::Promise> repairPath(const StorePath & path) override try { unsupported("repairPath"); } catch (...) { return {result::current_exception()}; } - void addSignatures(const StorePath & storePath, const StringSet & sigs) override; + kj::Promise> + addSignatures(const StorePath & storePath, const StringSet & sigs) override; kj::Promise> queryMissing(const std::vector & targets, StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, diff --git a/lix/libstore/store-api.hh b/lix/libstore/store-api.hh index c7ad1a4de..87a107a27 100644 --- a/lix/libstore/store-api.hh +++ b/lix/libstore/store-api.hh @@ -750,8 +750,9 @@ public: * Add signatures to the specified store path. The signatures are * not verified. */ - virtual void addSignatures(const StorePath & storePath, const StringSet & sigs) - { unsupported("addSignatures"); } + virtual kj::Promise> + addSignatures(const StorePath & storePath, const StringSet & sigs) + try { unsupported("addSignatures"); } catch (...) { return {result::current_exception()}; } /* Utility functions. */ diff --git a/lix/nix/sigs.cc b/lix/nix/sigs.cc index 1a7740c0a..63d736004 100644 --- a/lix/nix/sigs.cc +++ b/lix/nix/sigs.cc @@ -1,10 +1,12 @@ #include "lix/libcmd/command.hh" #include "lix/libmain/shared.hh" #include "lix/libstore/store-api.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/thread-pool.hh" #include "lix/libutil/signals.hh" #include +#include using namespace nix; @@ -42,7 +44,7 @@ struct CmdCopySigs : StorePathsCommand std::atomic added{0}; - auto doPath = [&](const Path & storePathS) { + auto doPath = [&](AsyncIoRoot & aio, const Path & storePathS) { checkInterrupt(); @@ -71,13 +73,16 @@ struct CmdCopySigs : StorePathsCommand } if (!newSigs.empty()) { - store->addSignatures(storePath, newSigs); + aio.blockOn(store->addSignatures(storePath, newSigs)); added += newSigs.size(); } }; - for (auto & storePath : storePaths) - pool.enqueue(std::bind(doPath, store->printStorePath(storePath))); + for (auto & storePath : storePaths) { + pool.enqueueWithAio( + std::bind(doPath, std::placeholders::_1, store->printStorePath(storePath)) + ); + } pool.process(); @@ -119,7 +124,7 @@ struct CmdSign : StorePathsCommand std::atomic added{0}; - auto doPath = [&](const Path & storePathS) { + auto doPath = [&](AsyncIoRoot & aio, const Path & storePathS) { checkInterrupt(); @@ -133,13 +138,16 @@ struct CmdSign : StorePathsCommand assert(!info2.sigs.empty()); if (!info->sigs.count(*info2.sigs.begin())) { - store->addSignatures(storePath, info2.sigs); + aio.blockOn(store->addSignatures(storePath, info2.sigs)); added++; } }; - for (auto & storePath : storePaths) - pool.enqueue(std::bind(doPath, store->printStorePath(storePath))); + for (auto & storePath : storePaths) { + pool.enqueueWithAio( + std::bind(doPath, std::placeholders::_1, store->printStorePath(storePath)) + ); + } pool.process();