Skip to content

Commit 9ce9c37

Browse files
committed
Prevent callback overruns in InvalidateBlock and RewindBlockIndex
1 parent 9bb32eb commit 9ce9c37

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

src/validation.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,6 +2642,14 @@ static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
26422642
}
26432643
}
26442644

2645+
static void LimitValidationInterfaceQueue() {
2646+
AssertLockNotHeld(cs_main);
2647+
2648+
if (GetMainSignals().CallbacksPending() > 10) {
2649+
SyncWithValidationInterfaceQueue();
2650+
}
2651+
}
2652+
26452653
/**
26462654
* Make the best chain active, in multiple steps. The result is either failure
26472655
* 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&
26702678
do {
26712679
boost::this_thread::interruption_point();
26722680

2673-
if (GetMainSignals().CallbacksPending() > 10) {
2674-
// Block until the validation queue drains. This should largely
2675-
// never happen in normal operation, however may happen during
2676-
// reindex, causing memory blowup if we run too far ahead.
2677-
// Note that if a validationinterface callback ends up calling
2678-
// ActivateBestChain this may lead to a deadlock! We should
2679-
// probably have a DEBUG_LOCKORDER test for this in the future.
2680-
SyncWithValidationInterfaceQueue();
2681-
}
2681+
// Block until the validation queue drains. This should largely
2682+
// never happen in normal operation, however may happen during
2683+
// reindex, causing memory blowup if we run too far ahead.
2684+
// Note that if a validationinterface callback ends up calling
2685+
// ActivateBestChain this may lead to a deadlock! We should
2686+
// probably have a DEBUG_LOCKORDER test for this in the future.
2687+
LimitValidationInterfaceQueue();
26822688

26832689
{
26842690
LOCK(cs_main);
@@ -2796,6 +2802,9 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
27962802
while (true) {
27972803
if (ShutdownRequested()) break;
27982804

2805+
// Make sure the queue of validation callbacks doesn't grow unboundedly.
2806+
LimitValidationInterfaceQueue();
2807+
27992808
LOCK(cs_main);
28002809
if (!chainActive.Contains(pindex)) break;
28012810
pindex_was_in_chain = true;
@@ -4285,6 +4294,9 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
42854294

42864295
tip = tip->pprev;
42874296
}
4297+
// Make sure the queue of validation callbacks doesn't grow unboundedly.
4298+
LimitValidationInterfaceQueue();
4299+
42884300
// Occasionally flush state to disk.
42894301
if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) {
42904302
LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));

0 commit comments

Comments
 (0)