wallet: Drain validation interface queue after notifications disconnect

When unloading a wallet, there may be unexecuted callbacks in the
validation interface queue that can still execute after we have
completed all of the other wallet shutdown tasks. Instead of letting
these run in the background, once the notifications are disconnected,
wait for the queue to drain before continuing with wallet shutdown.
This commit is contained in:
Ava Chow 2026-02-20 14:23:51 -08:00
parent 52992ebe1c
commit 98e8af4bb9
2 changed files with 16 additions and 3 deletions

View File

@ -169,7 +169,7 @@ bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet
WITH_LOCK(wallet->cs_wallet, wallet->WriteBestBlock());
// Unregister with the validation interface which also drops shared pointers.
wallet->m_chain_notifications_handler.reset();
wallet->DisconnectChainNotifications();
{
LOCK(context.wallets_mutex);
std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
@ -3117,7 +3117,7 @@ std::shared_ptr<CWallet> CWallet::CreateNew(WalletContext& context, const std::s
walletInstance->TopUpKeyPool();
if (chain && !AttachChain(walletInstance, *chain, /*rescan_required=*/false, error, warnings)) {
walletInstance->m_chain_notifications_handler.reset(); // Reset this pointer so that the wallet will actually be unloaded
walletInstance->DisconnectChainNotifications();
return nullptr;
}
@ -3158,7 +3158,7 @@ std::shared_ptr<CWallet> CWallet::LoadExisting(WalletContext& context, const std
walletInstance->TopUpKeyPool();
if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
walletInstance->m_chain_notifications_handler.reset(); // Reset this pointer so that the wallet will actually be unloaded
walletInstance->DisconnectChainNotifications();
return nullptr;
}
@ -4577,4 +4577,14 @@ std::optional<WalletTXO> CWallet::GetTXO(const COutPoint& outpoint) const
}
return it->second;
}
void CWallet::DisconnectChainNotifications()
{
if (m_chain_notifications_handler) {
m_chain_notifications_handler->disconnect();
chain().waitForNotifications();
m_chain_notifications_handler.reset();
}
}
} // namespace wallet

View File

@ -1072,6 +1072,9 @@ public:
//! Find the private key for the given key id from the wallet's descriptors, if available
//! Returns nullopt when no descriptor has the key or if the wallet is locked.
std::optional<CKey> GetKey(const CKeyID& keyid) const;
//! Disconnect chain notifications and wait for all notifications to be processed
void DisconnectChainNotifications();
};
/**