-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Closed
Labels
Description
When our chainstate activation sequence fails and we're running the GUI, we ask the user via a question box whether or not they'd like to re-run the sequence with fReindex = true
. Fun fact: despite the fact that this sequence is wrapped in a while loop, we only run it twice at most.
Lines 1539 to 1556 in 7ecb309
if (!fLoaded && !ShutdownRequested()) { | |
// first suggest a reindex | |
if (!fReset) { | |
bool fRet = uiInterface.ThreadSafeQuestion( | |
strLoadError + Untranslated(".\n\n") + _("Do you want to rebuild the block database now?"), | |
strLoadError.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.", | |
"", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT); | |
if (fRet) { | |
fReindex = true; | |
AbortShutdown(); | |
} else { | |
LogPrintf("Aborted block database rebuild. Exiting.\n"); | |
return false; | |
} | |
} else { | |
return InitError(strLoadError); | |
} | |
} |
If they answer yes, the sequence will always fail, because a chainstate will have already been initialized in the original run and InitializeChainstate
will throw a std::logic_error
:
Lines 4573 to 4594 in 7ecb309
CChainState& ChainstateManager::InitializeChainstate( | |
CTxMemPool* mempool, const std::optional<uint256>& snapshot_blockhash) | |
{ | |
bool is_snapshot = snapshot_blockhash.has_value(); | |
std::unique_ptr<CChainState>& to_modify = | |
is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate; | |
if (to_modify) { | |
throw std::logic_error("should not be overwriting a chainstate"); | |
} | |
to_modify.reset(new CChainState(mempool, m_blockman, snapshot_blockhash)); | |
// Snapshot chainstates and initial IBD chaintates always become active. | |
if (is_snapshot || (!is_snapshot && !m_active_chainstate)) { | |
LogPrintf("Switching active chainstate to %s\n", to_modify->ToString()); | |
m_active_chainstate = to_modify.get(); | |
} else { | |
throw std::logic_error("unexpected chainstate activation"); | |
} | |
return *to_modify; | |
} |
This always reproduces. To reproduce:
gdb ./src/qt/bitcoin-qt
(gdb) b InitializeChainstate
(gdb) # add breakpoint for the "if (!fLoaded && !ShutdownRequested()) {" line
(gdb) r # should stop at the breakpoint for InitializeChainstate
(gdb) c # to advance to the breakpoint for the "if (!fLoaded && !ShutdownRequested()) {" line
(gdb) set fLoaded=false
(gdb) c # should stop at the breakpoint for InitializeChainstate
(gdb) n # step through InitializeChainstate to see that it throws
We expect the re-run of the chainstate activation sequence to not always fail.