aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2019-02-13 17:17:59 -0800
committerPieter Wuille <pieter.wuille@gmail.com>2019-02-28 14:12:26 -0800
commit9ce9c37004440d6a329874dbf66b51666d497dcb (patch)
tree9216cb28ab8efd03c9f1396b9f2b3f84373c37d8 /src/validation.cpp
parent9bb32eb571a846b66ed3bac493f55cee11a3a1b9 (diff)
Prevent callback overruns in InvalidateBlock and RewindBlockIndex
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp30
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));