diff options
author | João Barbosa <joao.paulo.barbosa@gmail.com> | 2018-12-12 23:21:19 +0000 |
---|---|---|
committer | João Barbosa <joao.paulo.barbosa@gmail.com> | 2019-01-16 00:33:32 +0000 |
commit | 0cd9ad208c327127cc4616ccdc37557fad3cf381 (patch) | |
tree | 41393ae40812ce24475b650c89b70858d88f0336 /src/wallet/wallet.cpp | |
parent | 0a0b2ea11fde7becbdd1c04205336c3a39bffbc0 (diff) | |
download | bitcoin-0cd9ad208c327127cc4616ccdc37557fad3cf381.tar.xz |
rpc: Make unloadwallet wait for complete wallet unload
Github-Pull: #14941
Rebased-From: c37851d
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r-- | src/wallet/wallet.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 060325921f..e86aa04d18 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -81,13 +81,52 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name) return nullptr; } +static std::mutex g_wallet_release_mutex; +static std::condition_variable g_wallet_release_cv; +static std::set<CWallet*> g_unloading_wallet_set; + // Custom deleter for shared_ptr<CWallet>. static void ReleaseWallet(CWallet* wallet) { + // Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain + // so that it's in sync with the current chainstate. wallet->WalletLogPrintf("Releasing wallet\n"); wallet->BlockUntilSyncedToCurrentChain(); wallet->Flush(); + UnregisterValidationInterface(wallet); delete wallet; + // Wallet is now released, notify UnloadWallet, if any. + { + std::lock_guard<std::mutex> lock(g_wallet_release_mutex); + if (g_unloading_wallet_set.erase(wallet) == 0) { + // UnloadWallet was not called for this wallet, all done. + return; + } + } + g_wallet_release_cv.notify_all(); +} + +void UnloadWallet(std::shared_ptr<CWallet>&& wallet) +{ + // Mark wallet for unloading. + CWallet* pwallet = wallet.get(); + { + std::lock_guard<std::mutex> lock(g_wallet_release_mutex); + auto it = g_unloading_wallet_set.insert(pwallet); + assert(it.second); + } + // The wallet can be in use so it's not possible to explicitly unload here. + // Notify the unload intent so that all remaining shared pointers are + // released. + pwallet->NotifyUnload(); + // Time to ditch our shared_ptr and wait for ReleaseWallet call. + wallet.reset(); + { + std::unique_lock<std::mutex> lock(g_wallet_release_mutex); + while (g_unloading_wallet_set.count(pwallet) == 1) { + g_wallet_release_cv.wait(lock); + } + } } const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; |