diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2019-02-13 17:17:59 -0800 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2019-02-28 14:12:26 -0800 |
commit | 9ce9c37004440d6a329874dbf66b51666d497dcb (patch) | |
tree | 9216cb28ab8efd03c9f1396b9f2b3f84373c37d8 /src/validation.cpp | |
parent | 9bb32eb571a846b66ed3bac493f55cee11a3a1b9 (diff) |
Prevent callback overruns in InvalidateBlock and RewindBlockIndex
Diffstat (limited to 'src/validation.cpp')
-rw-r--r-- | src/validation.cpp | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/src/validation.cpp b/src/validation.cpp index 8f7e9fba69..d0d2227664 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2642,6 +2642,14 @@ static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) { } } +static void LimitValidationInterfaceQueue() { + AssertLockNotHeld(cs_main); + + if (GetMainSignals().CallbacksPending() > 10) { + SyncWithValidationInterfaceQueue(); + } +} + /** * Make the best chain active, in multiple steps. The result is either failure * or an activated best chain. pblock is either nullptr or a pointer to a block @@ -2670,15 +2678,13 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& do { boost::this_thread::interruption_point(); - if (GetMainSignals().CallbacksPending() > 10) { - // Block until the validation queue drains. This should largely - // never happen in normal operation, however may happen during - // reindex, causing memory blowup if we run too far ahead. - // Note that if a validationinterface callback ends up calling - // ActivateBestChain this may lead to a deadlock! We should - // probably have a DEBUG_LOCKORDER test for this in the future. - SyncWithValidationInterfaceQueue(); - } + // Block until the validation queue drains. This should largely + // never happen in normal operation, however may happen during + // reindex, causing memory blowup if we run too far ahead. + // Note that if a validationinterface callback ends up calling + // ActivateBestChain this may lead to a deadlock! We should + // probably have a DEBUG_LOCKORDER test for this in the future. + LimitValidationInterfaceQueue(); { LOCK(cs_main); @@ -2796,6 +2802,9 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c while (true) { if (ShutdownRequested()) break; + // Make sure the queue of validation callbacks doesn't grow unboundedly. + LimitValidationInterfaceQueue(); + LOCK(cs_main); if (!chainActive.Contains(pindex)) break; pindex_was_in_chain = true; @@ -4285,6 +4294,9 @@ bool CChainState::RewindBlockIndex(const CChainParams& params) tip = tip->pprev; } + // Make sure the queue of validation callbacks doesn't grow unboundedly. + LimitValidationInterfaceQueue(); + // Occasionally flush state to disk. if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) { LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state)); |