From 8af4f886e212346afdd1d40789f96f1321da96c5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 5 Jan 2021 11:47:29 +0100 Subject: [PATCH] Fix deadlock in LocalStore::addSignatures() Fixes #4367. --- src/libstore/local-store.cc | 95 +++++++++++++++++++------------------ src/libstore/local-store.hh | 2 + 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index c52d4b62a..702e7b136 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -736,57 +736,62 @@ void LocalStore::queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept { try { - callback(retrySQLite>([&]() { + callback(retrySQLite>([&]() { auto state(_state.lock()); - - /* Get the path info. */ - auto useQueryPathInfo(state->stmts->QueryPathInfo.use()(printStorePath(path))); - - if (!useQueryPathInfo.next()) - return std::shared_ptr(); - - auto id = useQueryPathInfo.getInt(0); - - auto narHash = Hash::dummy; - try { - narHash = Hash::parseAnyPrefixed(useQueryPathInfo.getStr(1)); - } catch (BadHash & e) { - throw Error("invalid-path entry for '%s': %s", printStorePath(path), e.what()); - } - - auto info = std::make_shared(path, narHash); - - info->id = id; - - info->registrationTime = useQueryPathInfo.getInt(2); - - auto s = (const char *) sqlite3_column_text(state->stmts->QueryPathInfo, 3); - if (s) info->deriver = parseStorePath(s); - - /* Note that narSize = NULL yields 0. */ - info->narSize = useQueryPathInfo.getInt(4); - - info->ultimate = useQueryPathInfo.getInt(5) == 1; - - s = (const char *) sqlite3_column_text(state->stmts->QueryPathInfo, 6); - if (s) info->sigs = tokenizeString(s, " "); - - s = (const char *) sqlite3_column_text(state->stmts->QueryPathInfo, 7); - if (s) info->ca = parseContentAddressOpt(s); - - /* Get the references. */ - auto useQueryReferences(state->stmts->QueryReferences.use()(info->id)); - - while (useQueryReferences.next()) - info->references.insert(parseStorePath(useQueryReferences.getStr(0))); - - return info; + return queryPathInfoInternal(*state, path); })); } catch (...) { callback.rethrow(); } } +std::shared_ptr LocalStore::queryPathInfoInternal(State & state, const StorePath & path) +{ + /* Get the path info. */ + auto useQueryPathInfo(state.stmts->QueryPathInfo.use()(printStorePath(path))); + + if (!useQueryPathInfo.next()) + return std::shared_ptr(); + + auto id = useQueryPathInfo.getInt(0); + + auto narHash = Hash::dummy; + try { + narHash = Hash::parseAnyPrefixed(useQueryPathInfo.getStr(1)); + } catch (BadHash & e) { + throw Error("invalid-path entry for '%s': %s", printStorePath(path), e.what()); + } + + auto info = std::make_shared(path, narHash); + + info->id = id; + + info->registrationTime = useQueryPathInfo.getInt(2); + + auto s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 3); + if (s) info->deriver = parseStorePath(s); + + /* Note that narSize = NULL yields 0. */ + info->narSize = useQueryPathInfo.getInt(4); + + info->ultimate = useQueryPathInfo.getInt(5) == 1; + + s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 6); + if (s) info->sigs = tokenizeString(s, " "); + + s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 7); + if (s) info->ca = parseContentAddressOpt(s); + + /* Get the references. */ + auto useQueryReferences(state.stmts->QueryReferences.use()(info->id)); + + while (useQueryReferences.next()) + info->references.insert(parseStorePath(useQueryReferences.getStr(0))); + + return info; +} + + /* Update path info in the database. */ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info) { @@ -1608,7 +1613,7 @@ void LocalStore::addSignatures(const StorePath & storePath, const StringSet & si SQLiteTxn txn(state->db); - auto info = std::const_pointer_cast(std::shared_ptr(queryPathInfo(storePath))); + auto info = std::const_pointer_cast(queryPathInfoInternal(*state, storePath)); info->sigs.insert(sigs.begin(), sigs.end()); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index ae9497b2e..6d29c5960 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -235,6 +235,8 @@ private: void verifyPath(const Path & path, const StringSet & store, PathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors); + std::shared_ptr queryPathInfoInternal(State & state, const StorePath & path); + void updatePathInfo(State & state, const ValidPathInfo & info); void upgradeStore6();