Inconsistent locking behavior in LoadChainTip #15967

issue deadalnix opened this issue on May 6, 2019
  1. deadalnix commented at 10:28 PM on May 6, 2019: none

    LoadChainTip requires cs_main to be locked. Under some conditions, it may call ActivateBestChain. However, ActivateBestChain requires cs_main NOT to be taken when called.

  2. deadalnix renamed this:
    Inconsistent licking behavior in LoadChainTip
    Inconsistent locking behavior in LoadChainTip
    on May 6, 2019
  3. practicalswift commented at 9:59 AM on May 7, 2019: contributor

    Confirming that there appears to be an inconsistency:

    $ grep -B11 '^        if (!ActivateBestChain(state, chainparams)) {' src/validation.cpp
    bool LoadChainTip(const CChainParams& chainparams)
    {
        AssertLockHeld(cs_main);
    
        if (chainActive.Tip() && chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) return true;
    
        if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) {
            // In case we just added the genesis block, connect it now, so
            // that we always have a chainActive.Tip() when we return.
            LogPrintf("%s: Connecting genesis block...\n", __func__);
            CValidationState state;
            if (!ActivateBestChain(state, chainparams)) {
    $ grep -A2 -E '^bool ActivateBestChain' src/validation.cpp
    bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) {
        return g_chainstate.ActivateBestChain(state, chainparams, std::move(pblock));
    }
    $ grep -A5 -E '^bool CChainState::ActivateBestChain\(' src/validation.cpp
    bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) {
        // Note that while we're often called here from ProcessNewBlock, this is
        // far from a guarantee. Things in the P2P/RPC will often end up calling
        // us in the middle of ProcessNewBlock - do not assume pblock is set
        // sanely for performance or correctness!
        AssertLockNotHeld(cs_main);
    $ git diff
    diff --git a/src/validation.h b/src/validation.h
    index 7ab6adaf3..5f19f32b4 100644
    --- a/src/validation.h
    +++ b/src/validation.h
    @@ -257,7 +257,7 @@ bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::P
      * May not be called with cs_main held. May not be called in a
      * validationinterface callback.
      */
    -bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>());
    +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>()) LOCKS_EXCLUDED(cs_main);
     CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
    
     /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
    
    $ make
    …
     validation.cpp:3959:14: error: cannot call function 'ActivateBestChain' while mutex 'cs_main' is held [-Werror,-Wthread-safety-analysis]
            if (!ActivateBestChain(state, chainparams)) {
                 ^
    1 error generated.
    

    I just submitted #15971 to add compile-time checking for some negative locking requirements in the validation code, but that PR does not address this case.

    Updated: Had totally forgotten that I submitted #15721 -- which adds LOCKS_EXCLUDED(cs_main) to CChainState::ActivateBestChain -- back in April too :-)

  4. MarcoFalke closed this on May 17, 2019

  5. MarcoFalke referenced this in commit a822a0e4f6 on May 17, 2019
  6. Munkybooty referenced this in commit 9a7b4cab65 on Oct 17, 2021
  7. Munkybooty referenced this in commit 08710599bf on Oct 22, 2021
  8. Munkybooty referenced this in commit 083b301262 on Oct 22, 2021
  9. Munkybooty referenced this in commit a8807d2dce on Oct 23, 2021
  10. Munkybooty referenced this in commit 5a319a15ce on Oct 26, 2021
  11. Munkybooty referenced this in commit 69c9144d01 on Oct 28, 2021
  12. DrahtBot locked this on Dec 16, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-14 18:14 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me