Skip to content

Commit

Permalink
Set notifications m_tip_block in LoadChainTip()
Browse files Browse the repository at this point in the history
Ensure KernelNotifications m_tip_block is set even if no new block arrives.

Additionally, have node init always wait for this to happen.
  • Loading branch information
Sjors committed Dec 6, 2024
1 parent 2eccb8b commit 37946c0
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 8 deletions.
16 changes: 13 additions & 3 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1770,7 +1770,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)

node.background_init_thread = std::thread(&util::TraceThread, "initload", [=, &chainman, &args, &node] {
ScheduleBatchPriority();
// Import blocks
// Import blocks and ActivateBestChain()
ImportBlocks(chainman, vImportFiles);
if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
LogPrintf("Stopping after block import\n");
Expand All @@ -1793,8 +1793,18 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
});

// Wait for genesis block to be processed
if (WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip() == nullptr)) {
/*
* Wait for genesis block to be processed. Typically kernel_notifications.m_tip_block
* has already been set by a call to LoadChainTip() in CompleteChainstateInitialization().
* But this is skipped if the chainstate doesn't exist yet or is being wiped:
*
* 1. first startup with an empty datadir
* 2. reindex
* 3. reindex-chainstate
*
* In these case it's connected by a call to ActivateBestChain() in the initload thread.
*/
{
WAIT_LOCK(kernel_notifications.m_tip_block_mutex, lock);
kernel_notifications.m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
return !kernel_notifications.m_tip_block.IsNull() || ShutdownRequested(node);
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/mining.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ class Mining
virtual std::optional<BlockRef> getTip() = 0;

/**
* Waits for the connected tip to change. If the tip was not connected on
* startup, this will wait.
* Waits for the connected tip to change. During node initialization, this will
* wait until the tip is connected.
*
* @param[in] current_tip block hash of the current chain tip. Function waits
* for the chain tip to differ from this.
Expand Down
1 change: 1 addition & 0 deletions src/node/blockstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ class BlockManager
void CleanupBlockRevFiles() const;
};

// Calls ActivateBestChain() even if no blocks are imported.
void ImportBlocks(ChainstateManager& chainman, std::span<const fs::path> import_paths);
} // namespace node

Expand Down
6 changes: 3 additions & 3 deletions src/node/kernel_notifications.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ class KernelNotifications : public kernel::Notifications

Mutex m_tip_block_mutex;
std::condition_variable m_tip_block_cv GUARDED_BY(m_tip_block_mutex);
//! The block for which the last blockTip notification was received for.
//! The initial ZERO means that no block has been connected yet, which may
//! be true even long after startup, until shutdown.
//! The block for which the last blockTip notification was received.
//! It's first set when the tip is connected during node initialization.
//! Might be unset during an early shutdown.
uint256 m_tip_block GUARDED_BY(m_tip_block_mutex){uint256::ZERO};

private:
Expand Down
7 changes: 7 additions & 0 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4721,6 +4721,13 @@ bool Chainstate::LoadChainTip()
m_chain.Height(),
FormatISO8601DateTime(tip->GetBlockTime()),
GuessVerificationProgress(m_chainman.GetParams().TxData(), tip));

// Ensure KernelNotifications m_tip_block is set even if no new block arrives.
if (this->GetRole() != ChainstateRole::BACKGROUND) {
// Ignoring return value for now.
(void)m_chainman.GetNotifications().blockTip(GetSynchronizationState(/*init=*/true, m_chainman.m_blockman.m_blockfiles_indexed), *pindex);
}

return true;
}

Expand Down

0 comments on commit 37946c0

Please sign in to comment.