diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1597,15 +1597,15 @@
     BlockHash hash(uint256S(strHash));
     CValidationState state;
 
+    CBlockIndex *pblockindex;
     {
         LOCK(cs_main);
-        CBlockIndex *pblockindex = LookupBlockIndex(hash);
+        pblockindex = LookupBlockIndex(hash);
         if (!pblockindex) {
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
         }
-
-        FinalizeBlockAndInvalidate(config, state, pblockindex);
     }
+    FinalizeBlockAndInvalidate(config, state, pblockindex);
 
     if (state.IsValid()) {
         ActivateBestChain(config, state);
diff --git a/src/validation.h b/src/validation.h
--- a/src/validation.h
+++ b/src/validation.h
@@ -639,8 +639,7 @@
  * A finalized block can not be reorged in any way.
  */
 bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state,
-                                CBlockIndex *pindex)
-    EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+                                CBlockIndex *pindex);
 
 /** Mark a block as invalid. */
 bool InvalidateBlock(const Config &config, CValidationState &state,
diff --git a/src/validation.cpp b/src/validation.cpp
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2829,6 +2829,14 @@
     }
 }
 
+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
@@ -2863,15 +2871,13 @@
     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);
@@ -3034,6 +3040,9 @@
             break;
         }
 
+        // Make sure the queue of validation callbacks doesn't grow unboundedly.
+        LimitValidationInterfaceQueue();
+
         LOCK(cs_main);
 
         if (!chainActive.Contains(pindex)) {
@@ -3126,26 +3135,29 @@
 
 bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state,
                                 CBlockIndex *pindex) {
-    AssertLockHeld(cs_main);
-    if (!FinalizeBlockInternal(config, state, pindex)) {
-        // state is set by FinalizeBlockInternal.
-        return false;
-    }
+    {
+        LOCK(cs_main);
+        if (!FinalizeBlockInternal(config, state, pindex)) {
+            // state is set by FinalizeBlockInternal.
+            return false;
+        }
 
-    // We have a valid candidate, make sure it is not parked.
-    if (pindex->nStatus.isOnParkedChain()) {
-        UnparkBlock(pindex);
+        // We have a valid candidate, make sure it is not parked.
+        if (pindex->nStatus.isOnParkedChain()) {
+            UnparkBlock(pindex);
+        }
     }
 
     // If the finalized block is not on the active chain, we need to rewind.
-    if (!AreOnTheSameFork(pindex, chainActive.Tip())) {
-        const CBlockIndex *pindexFork = chainActive.FindFork(pindex);
-        CBlockIndex *pindexToInvalidate =
-            chainActive.Tip()->GetAncestor(pindexFork->nHeight + 1);
-        return InvalidateBlock(config, state, pindexToInvalidate);
+    if (AreOnTheSameFork(pindex, chainActive.Tip())) {
+        return true;
     }
 
-    return true;
+    const CBlockIndex *pindexFork = chainActive.FindFork(pindex);
+    CBlockIndex *pindexToInvalidate =
+        chainActive.Tip()->GetAncestor(pindexFork->nHeight + 1);
+
+    return InvalidateBlock(config, state, pindexToInvalidate);
 }
 
 bool InvalidateBlock(const Config &config, CValidationState &state,