From cee5bf99f7ca070dae15fbefc7646a692a8fcb60 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 22 Oct 2023 00:46:58 +0700 Subject: [PATCH] fix: double lock of deterministicMNManager->cs Logs: node1 2023-10-21T16:46:03.990302Z (mocktime: 2014-12-04T17:33:19Z) [httpworker.1] DOUBLE LOCK DETECTED node1 2023-10-21T16:46:03.990322Z (mocktime: 2014-12-04T17:33:19Z) [httpworker.1] Lock order: node1 2023-10-21T16:46:03.990339Z (mocktime: 2014-12-04T17:33:19Z) [httpworker.1] 'cs_main' in miner.cpp:129 (in thread 'httpworker.1') node1 2023-10-21T16:46:03.990353Z (mocktime: 2014-12-04T17:33:19Z) [httpworker.1] 'm_mempool.cs' in miner.cpp:129 (in thread 'httpworker.1') node1 2023-10-21T16:46:03.990366Z (mocktime: 2014-12-04T17:33:19Z) [httpworker.1] (*) 'deterministicMNManager->cs' in evo/cbtx.cpp:114 (in thread 'httpworker.1') node1 2023-10-21T16:46:03.990439Z (mocktime: 2014-12-04T17:33:19Z) [httpworker.1] (*) 'cs' in ./evo/deterministicmns.h:614 (in thread 'httpworker.1') node1 2023-10-21T16:46:04.003619Z (mocktime: 2014-12-04T17:33:19Z) [httpworker.1] Posix Signal: Aborted No debug information available for stacktrace. You should add debug information and then run: dashd -printcrashinfo=bvcgc43iinzgc43ijfxgm3ybaacwiyltnbsbkudponuxqictnftw4ylmhiqecytpoj2gkzaphcbzaaaaaaaaayeurhimekiaaav6ldwqyiuqaafwsoe5bqrjaaahz6eh2dbcsaaakhhzaaaaaaaaanreseaaaaaaacgguliaaaaaaadyauwqaaaaaaacp3daaaaaaaaamxigcaaaaaaablpulyaaaaaaadovy3yaaaaaaahj7vbaaaaaaaadnbsdaaaaaaaaaa====== Part of backtrace: #9 UniqueLock, std::unique_lock >::UniqueLock (fTry=false, nLine=615, pszFile=0x55a9f71a3710 "./evo/deterministicmns.h", pszName=0x55a9f719caff "cs", mutexIn=..., this=0x7f7e1e71b250) at ./sync.h:164 #10 CDeterministicMNManager::GetListForBlock (this=0x55a9f84d06b0, pindex=0x7f7db03621c0) at ./evo/deterministicmns.h:615 #11 0x000055a9f6612258 in llmq::utils::ComputeQuorumMembersByQuarterRotation (pCycleQuorumBaseBlockIndex=0x7f7db03a6930, llmqParams=...) at /usr/include/c++/12/bits/unique_ptr.h:191 #12 llmq::utils::GetAllQuorumMembers (llmqType=, pQuorumBaseBlockIndex=0x7f7db0359bc0, reset_cache=reset_cache@entry=false) at llmq/utils.cpp:150 #13 0x000055a9f694d957 in CDeterministicMNManager::HandleQuorumCommitment (qc=..., pQuorumBaseBlockIndex=, mnList=..., debugLogs=debugLogs@entry=false) at evo/deterministicmns.cpp:989 #14 0x000055a9f695c455 in CDeterministicMNManager::BuildNewListFromBlock (this=, block=..., pindexPrev=pindexPrev@entry=0x7f7db03c1ac0, state=..., view=..., mnListRet=..., debugLogs=false) at evo/deterministicmns.cpp:918 #15 0x000055a9f692e7cd in CalcCbTxMerkleRootMNList (block=..., pindexPrev=pindexPrev@entry=0x7f7db03c1ac0, merkleRootRet=..., state=..., view=...) at /usr/include/c++/12/bits/unique_ptr.h:191 #16 0x000055a9f6a352ed in BlockAssembler::CreateNewBlock (this=this@entry=0x7f7e1e71f0b0, scriptPubKeyIn=...) at ./validation.h:649 #17 0x000055a9f6771c49 in generateBlocks (chainman=..., mempool=..., evodb=..., llmq_ctx=..., coinbase_script=..., nGenerate=10, nMaxTries=) at rpc/mining.cpp:167 #18 0x000055a9f677a496 in generatetoaddress (request=...) at /usr/include/c++/12/bits/unique_ptr.h:191 #19 0x000055a9f671ea02 in CRPCCommand::CRPCCommand(char const*, char const*, UniValue (*)(JSONRPCRequest const&), std::initializer_list)::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}::operator()(JSONRPCRequest const&, UniValue&, bool) const (__closure=, result=..., request=...) at ./rpc/server.h:120 --- src/evo/cbtx.cpp | 2 -- src/evo/deterministicmns.cpp | 8 +++----- src/evo/deterministicmns.h | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 6e44a0dcaaa0ac..6cc74d1de796b2 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -111,8 +111,6 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, BlockValidationState& state, const CCoinsViewCache& view) { - LOCK(deterministicMNManager->cs); - try { static int64_t nTimeDMN = 0; static int64_t nTimeSMNL = 0; diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 12baa3cfcec961..ebe54f99f4133f 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -613,8 +613,6 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde int nHeight = pindex->nHeight; try { - LOCK(cs); - if (!BuildNewListFromBlock(block, pindex->pprev, state, view, newList, true)) { // pass the state returned by the function above return false; @@ -626,6 +624,8 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde newList.SetBlockHash(pindex->GetBlockHash()); + LOCK(cs); + oldList = GetListForBlockInternal(pindex->pprev); diff = oldList.BuildDiff(newList); @@ -708,11 +708,9 @@ void CDeterministicMNManager::UpdatedBlockTip(const CBlockIndex* pindex) bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, BlockValidationState& state, const CCoinsViewCache& view, CDeterministicMNList& mnListRet, bool debugLogs) { - AssertLockHeld(cs); - int nHeight = pindexPrev->nHeight + 1; - CDeterministicMNList oldList = GetListForBlockInternal(pindexPrev); + CDeterministicMNList oldList = this->GetListForBlock(pindexPrev); CDeterministicMNList newList = oldList; newList.SetBlockHash(uint256()); // we can't know the final block hash, so better not return a (invalid) block hash newList.SetHeight(nHeight); diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 8af688c8228970..cf7d7cf0262f55 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -607,7 +607,7 @@ class CDeterministicMNManager // the returned list will not contain the correct block hash (we can't know it yet as the coinbase TX is not updated yet) bool BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, BlockValidationState& state, const CCoinsViewCache& view, - CDeterministicMNList& mnListRet, bool debugLogs) EXCLUSIVE_LOCKS_REQUIRED(cs); + CDeterministicMNList& mnListRet, bool debugLogs) LOCKS_EXCLUDED(cs); static void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, const CBlockIndex* pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs); CDeterministicMNList GetListForBlock(const CBlockIndex* pindex) LOCKS_EXCLUDED(cs) {