Merge #6002: fix: missing lock cs_wallet in rpc/evo

10869fff3b fix: order of locks cs_wallet and cs_main in rpc/evo (Konstantin Akimov)

Pull request description:

  ## Issue being fixed or feature implemented
  Changing order of locking `cs_main` and `cs_wallet` to prevent a deadlock.

  There's call `protx_list` -> `BuildDMNListEntry` -> `CheckWalletOwnsScript`:
  ```
  return WITH_LOCK(pwallet->cs_wallet, return pwallet->IsMine(script)) == isminetype::ISMINE_SPENDABLE;
  ```

  It can cause a deadlock due to wrong order of locks (cs_wallet supposed to be blocked in prior of cs_main)

  ## What was done?
  This PR adds and extra lock of cs_wallet and reduce scope of cs_main for a bit

  ## How Has This Been Tested?
  Deadlock warning is reproduced with this PR: https://github.com/dashpay/dash/pull/6003

  ## Breaking Changes
  N/A

  ## Checklist:
  - [x] I have performed a self-review of my own code
  - [ ] I have commented my code, particularly in hard-to-understand areas
  - [ ] I have added or updated relevant unit/integration/functional/e2e tests
  - [ ] I have made corresponding changes to the documentation
  - [x] I have assigned this pull request to a milestone

Top commit has no ACKs.

Tree-SHA512: 6d166fe7c47067c1c6d889d87e015ff3bc43aa9f66234341840cc8465ce00a79e7140bc09cbdb2fd08feaae5463b320e0b66bbe410422783f86cbc9d616af6b3
This commit is contained in:
pasta 2024-05-03 10:13:20 -05:00
commit 3b2c8bdcc5
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984

View File

@ -1372,7 +1372,6 @@ static UniValue protx_list(const JSONRPCRequest& request, CDeterministicMNManage
throw std::runtime_error("\"protx list wallet\" not supported when wallet is disabled");
}
#ifdef ENABLE_WALLET
LOCK2(wallet->cs_wallet, cs_main);
if (request.params.size() > 4) {
protx_list_help(request);
@ -1380,6 +1379,7 @@ static UniValue protx_list(const JSONRPCRequest& request, CDeterministicMNManage
bool detailed = !request.params[1].isNull() ? ParseBoolV(request.params[1], "detailed") : false;
LOCK2(wallet->cs_wallet, cs_main);
int height = !request.params[2].isNull() ? ParseInt32V(request.params[2], "height") : chainman.ActiveChain().Height();
if (height < 1 || height > chainman.ActiveChain().Height()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified");
@ -1408,10 +1408,13 @@ static UniValue protx_list(const JSONRPCRequest& request, CDeterministicMNManage
protx_list_help(request);
}
LOCK(cs_main);
bool detailed = !request.params[1].isNull() ? ParseBoolV(request.params[1], "detailed") : false;
#ifdef ENABLE_WALLET
LOCK2(wallet ? wallet->cs_wallet : cs_main, cs_main);
#else
LOCK(cs_main);
#endif
int height = !request.params[2].isNull() ? ParseInt32V(request.params[2], "height") : chainman.ActiveChain().Height();
if (height < 1 || height > chainman.ActiveChain().Height()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified");