@@ -82,13 +82,52 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
8282 return nullptr ;
8383}
8484
85+ static Mutex g_wallet_release_mutex;
86+ static std::condition_variable g_wallet_release_cv;
87+ static std::set<CWallet*> g_unloading_wallet_set;
88+
8589// Custom deleter for shared_ptr<CWallet>.
8690static void ReleaseWallet (CWallet* wallet)
8791{
92+ // Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
93+ // so that it's in sync with the current chainstate.
8894 wallet->WalletLogPrintf (" Releasing wallet\n " );
8995 wallet->BlockUntilSyncedToCurrentChain ();
9096 wallet->Flush ();
97+ UnregisterValidationInterface (wallet);
9198 delete wallet;
99+ // Wallet is now released, notify UnloadWallet, if any.
100+ {
101+ LOCK (g_wallet_release_mutex);
102+ if (g_unloading_wallet_set.erase (wallet) == 0 ) {
103+ // UnloadWallet was not called for this wallet, all done.
104+ return ;
105+ }
106+ }
107+ g_wallet_release_cv.notify_all ();
108+ }
109+
110+ void UnloadWallet (std::shared_ptr<CWallet>&& wallet)
111+ {
112+ // Mark wallet for unloading.
113+ CWallet* pwallet = wallet.get ();
114+ {
115+ LOCK (g_wallet_release_mutex);
116+ auto it = g_unloading_wallet_set.insert (pwallet);
117+ assert (it.second );
118+ }
119+ // The wallet can be in use so it's not possible to explicitly unload here.
120+ // Notify the unload intent so that all remaining shared pointers are
121+ // released.
122+ pwallet->NotifyUnload ();
123+ // Time to ditch our shared_ptr and wait for ReleaseWallet call.
124+ wallet.reset ();
125+ {
126+ WAIT_LOCK (g_wallet_release_mutex, lock);
127+ while (g_unloading_wallet_set.count (pwallet) == 1 ) {
128+ g_wallet_release_cv.wait (lock);
129+ }
130+ }
92131}
93132
94133const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000 ;
0 commit comments