diff options
author | Russell Yanofsky <russ@yanofsky.org> | 2020-03-10 15:46:20 -0400 |
---|---|---|
committer | João Barbosa <joao.paulo.barbosa@gmail.com> | 2020-03-27 15:17:35 +0000 |
commit | ab31b9d6fe7b39713682e3f52d11238dbe042c16 (patch) | |
tree | f719291130d3322eaac867b793309f476d8872c1 /src/validationinterface.h | |
parent | 3e50fdbe4e5bb98194e88023468bd77dee78b26e (diff) |
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.
Diffstat (limited to 'src/validationinterface.h')
-rw-r--r-- | src/validationinterface.h | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/src/validationinterface.h b/src/validationinterface.h index 5707422635..f9a359b7ad 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -30,6 +30,14 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn); void UnregisterValidationInterface(CValidationInterface* pwalletIn); /** Unregister all wallets from core */ void UnregisterAllValidationInterfaces(); + +// Alternate registration functions that release a shared_ptr after the last +// notification is sent. These are useful for race-free cleanup, since +// unregistration is nonblocking and can return before the last notification is +// processed. +void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks); +void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks); + /** * Pushes a function to callback onto the notification queue, guaranteeing any * callbacks generated prior to now are finished when the function is called. @@ -163,7 +171,7 @@ protected: * Notifies listeners that a block which builds directly on our current tip * has been received and connected to the headers tree, though not validated yet */ virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {}; - friend void ::RegisterValidationInterface(CValidationInterface*); + friend void ::RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface>); friend void ::UnregisterValidationInterface(CValidationInterface*); friend void ::UnregisterAllValidationInterfaces(); }; @@ -173,7 +181,7 @@ class CMainSignals { private: std::unique_ptr<MainSignalsInstance> m_internals; - friend void ::RegisterValidationInterface(CValidationInterface*); + friend void ::RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface>); friend void ::UnregisterValidationInterface(CValidationInterface*); friend void ::UnregisterAllValidationInterfaces(); friend void ::CallFunctionInValidationInterfaceQueue(std::function<void ()> func); |