From 1c9394ad477d0c1ca0ab1caa6024a7e70c125d15 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 6 Feb 2018 13:32:53 -0500 Subject: Fix fast-shutdown hang on ThreadImport+GenesisWait If the user somehow manages to get into ShutdownRequested before ThreadImport gets to ActivateBestChain() we may hang waiting on condvar_GenesisWait forever. A simple wait_for and ShutdownRequested resolves this case. --- src/init.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 50643ff96b..14dd8fc8ac 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1645,12 +1645,19 @@ bool AppInitMain() // Wait for genesis block to be processed { WaitableLock lock(cs_GenesisWait); - while (!fHaveGenesis) { - condvar_GenesisWait.wait(lock); + // We previously could hang here if StartShutdown() is called prior to + // ThreadImport getting started, so instead we just wait on a timer to + // check ShutdownRequested() regularly. + while (!fHaveGenesis && !ShutdownRequested()) { + condvar_GenesisWait.wait_for(lock, std::chrono::milliseconds(500)); } uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait); } + if (ShutdownRequested()) { + return false; + } + // ********************************************************* Step 11: start node int chain_active_height; -- cgit v1.2.3 From dd2de47c6288654abb2c3eef29edcd1cc5f39fc9 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 6 Feb 2018 13:38:54 -0500 Subject: Fix fast-shutdown crash if genesis block was not loaded If the ShutdownRequested() check at the top of ActivateBestChain() returns false during initial genesis block load we will fail an assertion in UTXO DB flush as the best block hash IsNull(). To work around this, we move the check until after one round of ActivateBestChainStep(), ensuring the genesis block gets connected. --- src/validation.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 698ef9181d..4315ec1814 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2581,9 +2581,6 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& SyncWithValidationInterfaceQueue(); } - if (ShutdownRequested()) - break; - const CBlockIndex *pindexFork; bool fInitialDownload; { @@ -2630,6 +2627,13 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& } if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); + + // We check shutdown only after giving ActivateBestChainStep a chance to run once so that we + // never shutdown before connecting the genesis block during LoadChainTip(). Previously this + // caused an assert() failure during shutdown in such cases as the UTXO DB flushing checks + // that the best block hash is non-null. + if (ShutdownRequested()) + break; } while (pindexNewTip != pindexMostWork); CheckBlockIndex(chainparams.GetConsensus()); -- cgit v1.2.3