diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-10-24 16:41:18 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-10-24 16:44:43 +0200 |
commit | a74ed3a05b27886e0a674c328e7ae13da8cacadb (patch) | |
tree | 10e24cc89360cf83b69f4c490f026d7ddc6f3636 | |
parent | 9886590116b19b14b8dad38f70ff9df5af99064f (diff) | |
parent | 8907df9e02ec47ef249a7422faa766f06aa01e94 (diff) |
Merge #14453: rpc: Fix wallet unload during walletpassphrase timeout
8907df9e02ec47ef249a7422faa766f06aa01e94 qa: Ensure wallet unload during walletpassphrase timeout (João Barbosa)
321decffa1fbf213462d97e5372bd0c4eeb99635 rpc: Fix wallet unload during walletpassphrase timeout (João Barbosa)
Pull request description:
Replaces the raw wallet pointer in the `RPCRunLater` callback with a `std::weak_ptr` to check if the wallet is not expired.
To test:
```
bitcoind -regtest
bitcoin-cli -regtest encryptwallet foobar
bitcoin-cli -regtest walletpassphrase foobar 5 && bitcoin-cli -regtest unloadwallet ""
```
Fixes #14452.
Tree-SHA512: 311e839234f5fb7955ab5412a2cfc1903ee7132ea56a8ab992ede3614586834886bd65192b76531ae0aa3a526b38e70ca2e1cdbabe52995906ff97b49d93c268
-rw-r--r-- | src/wallet/rpcwallet.cpp | 20 | ||||
-rwxr-xr-x | test/functional/wallet_multiwallet.py | 5 |
2 files changed, 17 insertions, 8 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5b97ad3ca1..dc39ba3001 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1803,13 +1803,6 @@ static UniValue keypoolrefill(const JSONRPCRequest& request) } -static void LockWallet(CWallet* pWallet) -{ - LOCK(pWallet->cs_wallet); - pWallet->nRelockTime = 0; - pWallet->Lock(); -} - static UniValue walletpassphrase(const JSONRPCRequest& request) { std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); @@ -1879,7 +1872,18 @@ static UniValue walletpassphrase(const JSONRPCRequest& request) pwallet->TopUpKeyPool(); pwallet->nRelockTime = GetTime() + nSleepTime; - RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), std::bind(LockWallet, pwallet), nSleepTime); + + // Keep a weak pointer to the wallet so that it is possible to unload the + // wallet before the following callback is called. If a valid shared pointer + // is acquired in the callback then the wallet is still loaded. + std::weak_ptr<CWallet> weak_wallet = wallet; + RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] { + if (auto shared_wallet = weak_wallet.lock()) { + LOCK(shared_wallet->cs_wallet); + shared_wallet->Lock(); + shared_wallet->nRelockTime = 0; + } + }, nSleepTime); return NullUniValue; } diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 30ab750fac..c9108ae797 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -8,6 +8,7 @@ Verify that a bitcoind node can load multiple wallet files """ import os import shutil +import time from test_framework.test_framework import BitcoinTestFramework from test_framework.test_node import ErrorMatch @@ -273,7 +274,11 @@ class MultiWalletTest(BitcoinTestFramework): assert 'w1' not in self.nodes[0].listwallets() # Successfully unload the wallet referenced by the request endpoint + # Also ensure unload works during walletpassphrase timeout + w2.encryptwallet('test') + w2.walletpassphrase('test', 1) w2.unloadwallet() + time.sleep(1.1) assert 'w2' not in self.nodes[0].listwallets() # Successfully unload all wallets |