aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/init.cpp13
-rw-r--r--src/scheduler.cpp9
-rw-r--r--src/scheduler.h3
-rw-r--r--src/test/test_bitcoin.cpp1
-rw-r--r--src/validationinterface.cpp4
-rw-r--r--src/validationinterface.h2
6 files changed, 32 insertions, 0 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 94bba6820e..12f29a4ca8 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -215,6 +215,19 @@ void Shutdown()
fFeeEstimatesInitialized = false;
}
+ // FlushStateToDisk generates a SetBestChain callback, which we should avoid missing
+ FlushStateToDisk();
+
+ // After there are no more peers/RPC left to give us new data which may generate
+ // CValidationInterface callbacks, flush them...
+ GetMainSignals().FlushBackgroundCallbacks();
+
+ // Any future callbacks will be dropped. This should absolutely be safe - if
+ // missing a callback results in an unrecoverable situation, unclean shutdown
+ // would too. The only reason to do the above flushes is to let the wallet catch
+ // up with our current chain to avoid any strange pruning edge cases and make
+ // next startup faster by avoiding rescan.
+
{
LOCK(cs_main);
if (pcoinsTip != NULL) {
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index a76a87e10a..35bf0da4be 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -191,3 +191,12 @@ void SingleThreadedSchedulerClient::AddToProcessQueue(std::function<void (void)>
}
MaybeScheduleProcessQueue();
}
+
+void SingleThreadedSchedulerClient::EmptyQueue() {
+ bool should_continue = true;
+ while (should_continue) {
+ ProcessQueue();
+ LOCK(m_cs_callbacks_pending);
+ should_continue = !m_callbacks_pending.empty();
+ }
+}
diff --git a/src/scheduler.h b/src/scheduler.h
index 82036afdf0..6a079f7749 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -101,6 +101,9 @@ private:
public:
SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {}
void AddToProcessQueue(std::function<void (void)> func);
+
+ // Processes all remaining queue members on the calling thread, blocking until queue is empty
+ void EmptyQueue();
};
#endif
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index e6a8cc779d..3ba81ed17b 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -94,6 +94,7 @@ TestingSetup::~TestingSetup()
UnregisterNodeSignals(GetNodeSignals());
threadGroup.interrupt_all();
threadGroup.join_all();
+ GetMainSignals().FlushBackgroundCallbacks();
GetMainSignals().UnregisterBackgroundSignalScheduler();
UnloadBlockIndex();
delete pcoinsTip;
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 8edc7c398d..bf20d606f8 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -44,6 +44,10 @@ void CMainSignals::UnregisterBackgroundSignalScheduler() {
m_internals.reset(nullptr);
}
+void CMainSignals::FlushBackgroundCallbacks() {
+ m_internals->m_schedulerClient.EmptyQueue();
+}
+
CMainSignals& GetMainSignals()
{
return g_signals;
diff --git a/src/validationinterface.h b/src/validationinterface.h
index fbfe273b10..568da66df2 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -79,6 +79,8 @@ public:
void RegisterBackgroundSignalScheduler(CScheduler& scheduler);
/** Unregister a CScheduler to give callbacks which should run in the background - these callbacks will now be dropped! */
void UnregisterBackgroundSignalScheduler();
+ /** Call any remaining callbacks on the calling thread */
+ void FlushBackgroundCallbacks();
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
void TransactionAddedToMempool(const CTransactionRef &);