Skip to content

Commit

Permalink
Merge bitcoin#11126: Acquire cs_main lock before cs_wallet during wal…
Browse files Browse the repository at this point in the history
…let initialization

de9a1db Acquire cs_main lock before cs_wallet during wallet initialization (Russell Yanofsky)

Pull request description:

  `CWallet::MarkConflicted` may acquire the `cs_main` lock after `CWalletDB::LoadWallet` acquires the `cs_wallet` lock during wallet initialization. (`CWalletDB::LoadWallet` calls `ReadKeyValue` which calls `CWallet::LoadToWallet` which calls `CWallet::MarkConflicted`). This is the opposite order that `cs_main` and `cs_wallet` locks are acquired in the rest of the code, and so leads to `POTENTIAL DEADLOCK DETECTED` errors if bitcoin is built with `-DDEBUG_LOCKORDER`.

  This commit changes `CWallet::LoadWallet` (which calls `CWalletDB::LoadWallet`) to acquire both locks in the standard order.

  Error was reported by @luke-jr in https://botbot.me/freenode/bitcoin-core-dev/msg/90244330/

Tree-SHA512: 353fe21bc0a4a2828b41876897001a3c414d4b115ee7430925bd391d8bc396fca81661145d00996c1ba1a01516d9acf8b89fb5c3da27092f5f3aa7e37ef26ffa
  • Loading branch information
laanwj committed Aug 28, 2017
2 parents 9c833f4 + de9a1db commit df91e11
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 8 deletions.
17 changes: 10 additions & 7 deletions src/wallet/test/wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,12 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
empty_wallet();
}

static void AddKey(CWallet& wallet, const CKey& key)
{
LOCK(wallet.cs_wallet);
wallet.AddKeyPubKey(key, key.GetPubKey());
}

BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
{
LOCK(cs_main);
Expand All @@ -379,8 +385,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// and new block files.
{
CWallet wallet;
LOCK(wallet.cs_wallet);
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
AddKey(wallet, coinbaseKey);
BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip));
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN);
}
Expand All @@ -393,8 +398,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// file.
{
CWallet wallet;
LOCK(wallet.cs_wallet);
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
AddKey(wallet, coinbaseKey);
BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip));
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN);
}
Expand Down Expand Up @@ -599,8 +603,7 @@ class ListCoinsTestingSetup : public TestChain100Setup
wallet.reset(new CWallet(std::unique_ptr<CWalletDBWrapper>(new CWalletDBWrapper(&bitdb, "wallet_test.dat"))));
bool firstRun;
wallet->LoadWallet(firstRun);
LOCK(wallet->cs_wallet);
wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
AddKey(*wallet, coinbaseKey);
wallet->ScanForWalletTransactions(chainActive.Genesis());
}

Expand Down Expand Up @@ -635,7 +638,7 @@ class ListCoinsTestingSetup : public TestChain100Setup
BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
{
std::string coinbaseAddress = coinbaseKey.GetPubKey().GetID().ToString();
LOCK(wallet->cs_wallet);
LOCK2(cs_main, wallet->cs_wallet);

// Confirm ListCoins initially returns 1 coin grouped under coinbaseKey
// address.
Expand Down
3 changes: 2 additions & 1 deletion src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2978,13 +2978,14 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwa

DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
LOCK2(cs_main, cs_wallet);

fFirstRunRet = false;
DBErrors nLoadWalletRet = CWalletDB(*dbw,"cr+").LoadWallet(this);
if (nLoadWalletRet == DB_NEED_REWRITE)
{
if (dbw->Rewrite("\x04pool"))
{
LOCK(cs_wallet);
setInternalKeyPool.clear();
setExternalKeyPool.clear();
m_pool_key_to_index.clear();
Expand Down

0 comments on commit df91e11

Please sign in to comment.