mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-08 06:37:50 +02:00
mining: add interrupt()
Both waitTipChanged() and createNewBlock() can take a long time to return. Add a way for clients to interrupt them. The new m_interrupt_mining is safely accessed with a lock on m_tip_block_mutex, but it has no guard annotation. A more thorough solution is discussed here: https://github.com/bitcoin/bitcoin/pull/34184#discussion_r2743566474
This commit is contained in:
@@ -455,7 +455,7 @@ std::optional<BlockRef> GetTip(ChainstateManager& chainman)
|
||||
return BlockRef{tip->GetBlockHash(), tip->nHeight};
|
||||
}
|
||||
|
||||
bool CooldownIfHeadersAhead(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const BlockRef& last_tip)
|
||||
bool CooldownIfHeadersAhead(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const BlockRef& last_tip, bool& interrupt_mining)
|
||||
{
|
||||
uint256 last_tip_hash{last_tip.hash};
|
||||
|
||||
@@ -467,9 +467,12 @@ bool CooldownIfHeadersAhead(ChainstateManager& chainman, KernelNotifications& ke
|
||||
WAIT_LOCK(kernel_notifications.m_tip_block_mutex, lock);
|
||||
kernel_notifications.m_tip_block_cv.wait_until(lock, cooldown_deadline, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
|
||||
const auto tip_block = kernel_notifications.TipBlock();
|
||||
return chainman.m_interrupt || (tip_block && *tip_block != last_tip_hash);
|
||||
return chainman.m_interrupt || interrupt_mining || (tip_block && *tip_block != last_tip_hash);
|
||||
});
|
||||
if (chainman.m_interrupt) return false;
|
||||
if (chainman.m_interrupt || interrupt_mining) {
|
||||
interrupt_mining = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the tip changed during the wait, extend the deadline
|
||||
const auto tip_block = kernel_notifications.TipBlock();
|
||||
@@ -486,7 +489,7 @@ bool CooldownIfHeadersAhead(ChainstateManager& chainman, KernelNotifications& ke
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<BlockRef> WaitTipChanged(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const uint256& current_tip, MillisecondsDouble& timeout)
|
||||
std::optional<BlockRef> WaitTipChanged(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const uint256& current_tip, MillisecondsDouble& timeout, bool& interrupt)
|
||||
{
|
||||
Assume(timeout >= 0ms); // No internal callers should use a negative timeout
|
||||
if (timeout < 0ms) timeout = 0ms;
|
||||
@@ -499,16 +502,22 @@ std::optional<BlockRef> WaitTipChanged(ChainstateManager& chainman, KernelNotifi
|
||||
// always returns valid tip information when possible and only
|
||||
// returns null when shutting down, not when timing out.
|
||||
kernel_notifications.m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
|
||||
return kernel_notifications.TipBlock() || chainman.m_interrupt;
|
||||
return kernel_notifications.TipBlock() || chainman.m_interrupt || interrupt;
|
||||
});
|
||||
if (chainman.m_interrupt) return {};
|
||||
if (chainman.m_interrupt || interrupt) {
|
||||
interrupt = false;
|
||||
return {};
|
||||
}
|
||||
// At this point TipBlock is set, so continue to wait until it is
|
||||
// different then `current_tip` provided by caller.
|
||||
kernel_notifications.m_tip_block_cv.wait_until(lock, deadline, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
|
||||
return Assume(kernel_notifications.TipBlock()) != current_tip || chainman.m_interrupt;
|
||||
return Assume(kernel_notifications.TipBlock()) != current_tip || chainman.m_interrupt || interrupt;
|
||||
});
|
||||
if (chainman.m_interrupt || interrupt) {
|
||||
interrupt = false;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (chainman.m_interrupt) return {};
|
||||
|
||||
// Must release m_tip_block_mutex before getTip() locks cs_main, to
|
||||
// avoid deadlocks.
|
||||
|
||||
Reference in New Issue
Block a user