From b42ce5c0de4fa88a8ba4058a7d74425dc9e0178d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 12 Dec 2018 23:21:19 +0000 Subject: [PATCH] rpc: Make unloadwallet wait for complete wallet unload Github-Pull: #14941 Rebased-From: c37851d --- src/init.cpp | 1 + src/wallet/init.cpp | 6 ++++++ src/wallet/wallet.cpp | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index ccb5962c4..2d320a207 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -286,6 +286,7 @@ void Shutdown(InitInterfaces& interfaces) LogPrintf("%s: Unable to remove PID file: %s\n", __func__, fsbridge::get_filesystem_error_message(e)); } interfaces.chain_clients.clear(); + g_wallet_init_interface.Close(); UnregisterAllValidationInterfaces(); GetMainSignals().UnregisterBackgroundSignalScheduler(); GetMainSignals().UnregisterWithMempoolSignals(mempool); diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index e766deadb..70fbb681a 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -135,4 +135,10 @@ void WalletInit::Construct(InitInterfaces& interfaces) const } gArgs.SoftSetArg("-wallet", ""); interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient(*interfaces.chain, gArgs.GetArgs("-wallet"))); + auto wallets = GetWallets(); + while (!wallets.empty()) { + auto wallet = wallets.back(); + wallets.pop_back(); + RemoveWallet(wallet); + UnloadWallet(std::move(wallet)); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fdaafd518..946e02130 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -125,6 +125,29 @@ static void ReleaseWallet(CWallet* wallet) g_wallet_release_cv.notify_all(); } +void UnloadWallet(std::shared_ptr&& wallet) +{ + // Mark wallet for unloading. + CWallet* pwallet = wallet.get(); + { + std::lock_guard 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 lock(g_wallet_release_mutex); + while (g_unloading_wallet_set.count(pwallet) == 1) { + g_wallet_release_cv.wait(lock); + } + } +} + void UnloadWallet(std::shared_ptr&& wallet) { // Mark wallet for unloading.