From 588eb30b863e9ecf942396158adfc7f6f047d3e2 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 11 Mar 2019 14:31:51 +0100 Subject: [PATCH] Fix deadlock in CSigSharesManager::SendMessages (#2757) * Fix deadlock in CSigSharesManager::SendMessages Locking "cs" at this location caused a (potential) deadlock due to changed order of cs and cs_vNodes locking. This changes the method to not require the session object anymore which removes the need for locking. * Pass size of LLMQ instead of llmqType into CSigSharesInv::Init This allows use of sizes which are not supported in chainparams. --- src/llmq/quorums_signing_shares.cpp | 38 ++++++++++++++--------------- src/llmq/quorums_signing_shares.h | 4 +-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index ca52d2933884e..59ca1f3facd0f 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -65,10 +65,9 @@ std::string CSigSharesInv::ToString() const return str; } -void CSigSharesInv::Init(Consensus::LLMQType _llmqType) +void CSigSharesInv::Init(size_t size) { - size_t llmqSize = (size_t)(Params().GetConsensus().llmqs.at(_llmqType).size); - inv.resize(llmqSize, false); + inv.resize(size, false); } bool CSigSharesInv::IsSet(uint16_t quorumMember) const @@ -83,27 +82,30 @@ void CSigSharesInv::Set(uint16_t quorumMember, bool v) inv[quorumMember] = v; } -CSigSharesInv CBatchedSigShares::ToInv(Consensus::LLMQType llmqType) const +std::string CBatchedSigShares::ToInvString() const { CSigSharesInv inv; - inv.Init(llmqType); + // we use 400 here no matter what the real size is. We don't really care about that size as we just want to call ToString() + inv.Init(400); for (size_t i = 0; i < sigShares.size(); i++) { inv.inv[sigShares[i].first] = true; } - return inv; + return inv.ToString(); } template static void InitSession(CSigSharesNodeState::Session& s, const uint256& signHash, T& from) { + const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)from.llmqType); + s.llmqType = (Consensus::LLMQType)from.llmqType; s.quorumHash = from.quorumHash; s.id = from.id; s.msgHash = from.msgHash; s.signHash = signHash; - s.announced.Init((Consensus::LLMQType)from.llmqType); - s.requested.Init((Consensus::LLMQType)from.llmqType); - s.knows.Init((Consensus::LLMQType)from.llmqType); + s.announced.Init((size_t)params.size); + s.requested.Init((size_t)params.size); + s.knows.Init((size_t)params.size); } CSigSharesNodeState::Session& CSigSharesNodeState::GetOrCreateSessionFromShare(const llmq::CSigShare& sigShare) @@ -443,7 +445,7 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(CNode* pfrom, const CBatc } LogPrint("llmq", "CSigSharesManager::%s -- signHash=%s, shares=%d, new=%d, inv={%s}, node=%d\n", __func__, - sessionInfo.signHash.ToString(), batchedSigShares.sigShares.size(), sigShares.size(), batchedSigShares.ToInv(sessionInfo.llmqType).ToString(), pfrom->id); + sessionInfo.signHash.ToString(), batchedSigShares.sigShares.size(), sigShares.size(), batchedSigShares.ToInvString(), pfrom->id); if (sigShares.empty()) { return true; @@ -871,7 +873,8 @@ void CSigSharesManager::CollectSigSharesToRequest(std::unordered_mapllmqType); + const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)sigShare->llmqType); + inv.Init((size_t)params.size); } inv.inv[quorumMember] = true; session.knows.inv[quorumMember] = true; @@ -1101,14 +1105,8 @@ bool CSigSharesManager::SendMessages() std::vector msgs; for (auto& p : jt->second) { assert(!p.second.sigShares.empty()); - if (LogAcceptCategory("llmq")) { - LOCK(cs); - auto session = nodeStates[pnode->id].GetSessionBySignHash(p.first); - assert(session); - LogPrint("llmq", "CSigSharesManager::SendMessages -- QBSIGSHARES signHash=%s, inv={%s}, node=%d\n", - p.first.ToString(), p.second.ToInv(session->llmqType).ToString(), pnode->id); - } - + LogPrint("llmq", "CSigSharesManager::SendMessages -- QBSIGSHARES signHash=%s, inv={%s}, node=%d\n", + p.first.ToString(), p.second.ToInvString(), pnode->id); if (totalSigsCount + p.second.sigShares.size() > MAX_MSGS_TOTAL_BATCHED_SIGS) { g_connman->PushMessage(pnode, msgMaker.Make(NetMsgType::QBSIGSHARES, msgs), false); msgs.clear(); diff --git a/src/llmq/quorums_signing_shares.h b/src/llmq/quorums_signing_shares.h index beb781589d72e..d17be73c82ada 100644 --- a/src/llmq/quorums_signing_shares.h +++ b/src/llmq/quorums_signing_shares.h @@ -101,7 +101,7 @@ class CSigSharesInv READWRITE(AUTOBITSET(inv, (size_t)invSize)); } - void Init(Consensus::LLMQType _llmqType); + void Init(size_t size); bool IsSet(uint16_t quorumMember) const; void Set(uint16_t quorumMember, bool v); void Merge(const CSigSharesInv& inv2); @@ -127,7 +127,7 @@ class CBatchedSigShares READWRITE(sigShares); } - CSigSharesInv ToInv(Consensus::LLMQType llmqType) const; + std::string ToInvString() const; }; template