aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Corallo <git@bluematt.me>2017-12-04 18:57:55 -0500
committerMatt Corallo <git@bluematt.me>2017-12-26 11:54:49 -0500
commit36137497f1e2b3324ca84550f4f295dcd605d1fa (patch)
tree684bc166f66e54273396034cef46203eff8ca62b
parent5a933cefcc5e0595a1ec46fc5ea287aa163ecd3f (diff)
downloadbitcoin-36137497f1e2b3324ca84550f4f295dcd605d1fa.tar.xz
Block ActivateBestChain to empty validationinterface queue
-rw-r--r--src/test/test_bitcoin.cpp6
-rw-r--r--src/validation.cpp13
2 files changed, 16 insertions, 3 deletions
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index f52c8ccc21..6bd228a63a 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -69,9 +69,9 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
fs::create_directories(pathTemp);
gArgs.ForceSetArg("-datadir", pathTemp.string());
- // Note that because we don't bother running a scheduler thread here,
- // callbacks via CValidationInterface are unreliable, but that's OK,
- // our unit tests aren't testing multiple parts of the code at once.
+ // We have to run a scheduler thread to prevent ActivateBestChain
+ // from blocking due to queue overrun.
+ threadGroup.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
mempool.setSanityCheck(1.0);
diff --git a/src/validation.cpp b/src/validation.cpp
index 71a51c499c..23ce6509d5 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -40,6 +40,7 @@
#include <validationinterface.h>
#include <warnings.h>
+#include <future>
#include <sstream>
#include <boost/algorithm/string/replace.hpp>
@@ -2566,6 +2567,18 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
int nStopAtHeight = gArgs.GetArg("-stopatheight", DEFAULT_STOPATHEIGHT);
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.
+ std::promise<void> promise;
+ CallFunctionInValidationInterfaceQueue([&promise] {
+ promise.set_value();
+ });
+ promise.get_future().wait();
+ }
+
if (ShutdownRequested())
break;