mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-13 12:33:42 +02:00
Fix wallet unload race condition
Currently it's possible for ReleaseWallet to delete the CWallet pointer while it is processing BlockConnected, etc chain notifications. To fix this, unregister from notifications earlier in UnloadWallet instead of ReleaseWallet, and use a new RegisterSharedValidationInterface function to prevent the CValidationInterface shared_ptr from being deleted until the last notification is actually finished.
This commit is contained in:
parent
3e50fdbe4e
commit
ab31b9d6fe
9 changed files with 62 additions and 42 deletions
|
|
@ -75,8 +75,10 @@ CMainSignals& GetMainSignals()
|
|||
return g_signals;
|
||||
}
|
||||
|
||||
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||
ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
|
||||
void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> pwalletIn) {
|
||||
// Each connection captures pwalletIn to ensure that each callback is
|
||||
// executed before pwalletIn is destroyed. For more details see #18338.
|
||||
ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn.get()];
|
||||
conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
conns.TransactionAddedToMempool = g_signals.m_internals->TransactionAddedToMempool.connect(std::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, std::placeholders::_1));
|
||||
conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2));
|
||||
|
|
@ -87,6 +89,18 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
|||
conns.NewPoWValidBlock = g_signals.m_internals->NewPoWValidBlock.connect(std::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
void RegisterValidationInterface(CValidationInterface* callbacks)
|
||||
{
|
||||
// Create a shared_ptr with a no-op deleter - CValidationInterface lifecycle
|
||||
// is managed by the caller.
|
||||
RegisterSharedValidationInterface({callbacks, [](CValidationInterface*){}});
|
||||
}
|
||||
|
||||
void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
|
||||
{
|
||||
UnregisterValidationInterface(callbacks.get());
|
||||
}
|
||||
|
||||
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||
if (g_signals.m_internals) {
|
||||
g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue