mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-07-16 17:50:56 +02:00
init: wake genesis wait after ImportBlocks() returns
If shutdown interrupts ImportBlocks() before genesis activation, no blockTip notification is sent. The wait predicate allows shutdown to occur, but the condition variable is never notified, so init can remain stuck waiting for genesis activation. Notify the tip condition variable after ImportBlocks() returns so interrupted imports wake the wait and let it observe the shutdown request. Add test coverage for interrupting startup after reindex block files import begins, which exercises the path where ImportBlocks() can return before genesis activation.
This commit is contained in:
@@ -2045,10 +2045,16 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
}
|
||||
|
||||
/// \anchor initload
|
||||
node.background_init_thread = std::thread(&util::TraceThread, "initload", [=, &chainman, &args, &node] {
|
||||
node.background_init_thread = std::thread(&util::TraceThread, "initload", [=, &chainman, &args, &kernel_notifications, &node] {
|
||||
ScheduleBatchPriority();
|
||||
// Import blocks and ActivateBestChain()
|
||||
ImportBlocks(chainman, vImportFiles);
|
||||
// An interrupted import may return without activating genesis. Wake
|
||||
// the init thread's genesis wait, which is otherwise only notified
|
||||
// on blockTip, and that never fires when the import was interrupted
|
||||
// before activating genesis. This wakeup lets the wait observe the
|
||||
// shutdown request.
|
||||
WITH_LOCK(kernel_notifications.m_tip_block_mutex, kernel_notifications.m_tip_block_cv.notify_all());
|
||||
WITH_LOCK(::cs_main, chainman.UpdateIBDStatus());
|
||||
if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
|
||||
LogInfo("Stopping after block import");
|
||||
|
||||
@@ -63,6 +63,7 @@ class InitTest(BitcoinTestFramework):
|
||||
node.process.terminate()
|
||||
assert_equal(0, node.process.wait())
|
||||
|
||||
reindex_log_line = b'Reindexing block file blk00000.dat'
|
||||
lines_to_terminate_after = [
|
||||
b'Validating signatures for all blocks',
|
||||
b'scheduler thread start',
|
||||
@@ -87,16 +88,20 @@ class InitTest(BitcoinTestFramework):
|
||||
]
|
||||
if self.is_wallet_compiled():
|
||||
lines_to_terminate_after.append(b'Verifying wallet')
|
||||
lines_to_terminate_after.append(reindex_log_line)
|
||||
|
||||
for terminate_line in lines_to_terminate_after:
|
||||
self.log.info(f"Starting node and will terminate after line {terminate_line}")
|
||||
with node.busy_wait_for_debug_log([terminate_line]):
|
||||
extra_args = [*ALL_INDEX_ARGS]
|
||||
if terminate_line == reindex_log_line:
|
||||
extra_args += ['-reindex']
|
||||
if platform.system() == 'Windows':
|
||||
# CREATE_NEW_PROCESS_GROUP is required in order to be able
|
||||
# to terminate the child without terminating the test.
|
||||
node.start(extra_args=ALL_INDEX_ARGS, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
|
||||
node.start(extra_args=extra_args, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
|
||||
else:
|
||||
node.start(extra_args=ALL_INDEX_ARGS)
|
||||
node.start(extra_args=extra_args)
|
||||
self.log.debug("Terminating node after terminate line was found")
|
||||
sigterm_node()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user