wallet: Add missing cs_wallet/cs_KeyStore locks to wallet #11634

pull practicalswift wants to merge 4 commits into bitcoin:master from practicalswift:missing-wallet-locks changing 5 files +39 −28
  1. practicalswift commented at 9:33 am on November 8, 2017: contributor

    Add missing wallet locks:

    • Calling the function GetConflicts(...) requires holding the mutex cs_wallet
    • Calling the function IsSpent(...) requires holding the mutex cs_wallet
    • Accessing the variables mapKeys and mapCryptedKeys requires holding the mutex cs_KeyStore
    • Accessing the variable nTimeFirstKey requires holding the mutex cs_wallet
    • Accessing the variable mapWallet requires holding the mutex cs_wallet
    • Accessing the variable nTimeFirstKey requires holding the mutex cs_wallet
  2. fanquake added the label Wallet on Nov 8, 2017
  3. practicalswift force-pushed on Nov 8, 2017
  4. in src/wallet/wallet.cpp:4089 in b229a8ea1d outdated
    3959@@ -3953,6 +3960,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
    3960             for (const CWalletTx& wtxOld : vWtx)
    3961             {
    3962                 uint256 hash = wtxOld.GetHash();
    3963+                LOCK(walletInstance->cs_wallet);
    


    promag commented at 1:39 pm on November 8, 2017:

    Either:

    • lock once before the loop;
    • loop first with the lock to mapWallet.find(hash) for all vWtx and then loop again without the lock to walletdb.WriteTx();
    • lock only the mapWallet.find(hash).
  5. practicalswift force-pushed on Nov 8, 2017
  6. practicalswift commented at 1:53 pm on November 8, 2017: contributor
    @promag Thanks for reviewing! Feedback addressed. Looks good? :-)
  7. in src/wallet/wallet.cpp:4305 in e921615a90 outdated
    3956@@ -3950,6 +3957,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
    3957         {
    3958             CWalletDB walletdb(*walletInstance->dbw);
    3959 
    3960+            LOCK(walletInstance->cs_wallet);
    


    promag commented at 3:08 pm on November 8, 2017:
    This should be before the line above. Anyway, there is no need to lock this wallet since it’s a fresh instance, unknown to the remaining system. Unless you are adding the lock because of other asserts and if so please commit them to justify this change?

    practicalswift commented at 4:08 pm on November 8, 2017:

    Now moved before the line above. Without that lock we’ll trigger Clang thread safety analysis warnings when #11634 is merged due to:

    0src/wallet/wallet.h:    std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
    

    As agreed upon in #11226 (comment) all guard/lock annotations are added in #11634 and all extra locking is submitted as separate PR:s (such as this one).

    The annotations are compile-time only whereas the locks change run-time behaviour (and thus needs extra scrunity!).


    promag commented at 4:18 pm on November 8, 2017:

    As agreed upon in #11226 (comment) all guard/lock annotations are added in #11634 and all extra locking is submitted as separate PR:s (such as this one)

    I think you swapped the PR numbers?


    practicalswift commented at 9:55 pm on November 8, 2017:
    Yes, you’re right - the annotations are added in #11226 :-)
  8. practicalswift force-pushed on Nov 8, 2017
  9. promag commented at 8:36 pm on November 8, 2017: member
    utACK 007fcbf.
  10. luke-jr referenced this in commit a6b3c637e6 on Nov 11, 2017
  11. practicalswift force-pushed on Nov 21, 2017
  12. practicalswift commented at 4:58 pm on November 21, 2017: contributor

    Added another commit with two more missing locks:

    • calling function IsSpent requires holding mutex pwallet->cs_wallet exclusively
    • writing variable nWalletVersion, nWalletMaxVersion, nOrderPosNext and nTimeFirstKey require holding mutex cs_wallet
  13. practicalswift commented at 4:59 pm on November 21, 2017: contributor
    @promag Would you mind re-reviewing? :-)
  14. in src/wallet/wallet.cpp:4283 in fba0830bca outdated
    3995@@ -3991,8 +3996,11 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
    3996 
    3997         // No need to read and scan block if block was created before
    3998         // our wallet birthday (as adjusted for block time variability)
    3999-        while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) {
    4000-            pindexRescan = chainActive.Next(pindexRescan);
    4001+        {
    4002+            LOCK(walletInstance->cs_wallet);
    


    TheBlueMatt commented at 10:38 pm on December 12, 2017:
    Given this is effectively just the wallet’s constructor, might as well just take the lock further up and hold it the whole time.

    practicalswift commented at 3:31 pm on March 12, 2018:

    @TheBlueMatt Moving it further up will make the scope of the walletInstance->cs_wallet lock cover the ScanForWalletTransactions call. ScanForWalletTransactions locks cs_main giving us the lock order:

      1. cs_wallet
      1. cs_main

    This is a potential deadlock given that the opposite lock order is used extensively:

    0$ git grep "LOCK2(cs_main,.*cs_wallet);" | wc -l
    189
    

    Please advice :-)


    promag commented at 9:23 pm on March 14, 2018:
    A solution to that is to also lock cs_main.. but meh
  15. in src/wallet/wallet.h:793 in fba0830bca outdated
    788@@ -789,18 +789,21 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
    789 
    790     void SetNull()
    791     {
    792-        nWalletVersion = FEATURE_BASE;
    793-        nWalletMaxVersion = FEATURE_BASE;
    794+        {
    795+            LOCK(cs_wallet);
    


    TheBlueMatt commented at 7:43 pm on December 13, 2017:
    Same here. Just add a cs_wallet lock for the whole function.
  16. practicalswift force-pushed on Feb 22, 2018
  17. practicalswift force-pushed on Feb 22, 2018
  18. practicalswift commented at 8:25 pm on February 22, 2018: contributor
    @TheBlueMatt Thanks for reviewing! Feedback addressed. Please re-review :-)
  19. practicalswift force-pushed on Mar 2, 2018
  20. practicalswift commented at 4:58 pm on March 2, 2018: contributor
    Fixed build issue. Please re-review :-)
  21. MarcoFalke commented at 5:05 pm on March 2, 2018: member
    Given that https://github.com/bitcoin/bitcoin/pull/11226/files#diff-12635a58447c65585f51d32b7e04075bR857 is now closed, wouldn’t it make sense to add the clang annotations within this commit?
  22. practicalswift force-pushed on Mar 10, 2018
  23. practicalswift force-pushed on Mar 10, 2018
  24. practicalswift force-pushed on Mar 10, 2018
  25. practicalswift force-pushed on Mar 10, 2018
  26. practicalswift commented at 1:27 pm on March 10, 2018: contributor
    @MarcoFalke @TheBlueMatt @promag Thanks for reviewing. I’ve now addressed the feedback and added corresponding GUARDED_BY/EXCLUSIVE_LOCKS_REQUIRED annotations. Please re-review :-)
  27. in src/wallet/wallet.cpp:3900 in 8dcfcb265d outdated
    3937@@ -3930,6 +3938,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
    3938     int64_t nStart = GetTimeMillis();
    3939     bool fFirstRun = true;
    3940     CWallet *walletInstance = new CWallet(name, CWalletDBWrapper::Create(path));
    3941+    LOCK(walletInstance->cs_wallet);
    3942     DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
    


    MarcoFalke commented at 10:12 pm on March 11, 2018:
    Note that LoadWallet takes LOCK2(cs_main, cs_wallet), so taking cs_wallet before cs_main leads to a deadlock in case another thread takes cs_main and then cs_wallet, no?

    practicalswift commented at 3:32 pm on March 12, 2018:
    Thanks. Now fixed. See #11634 (review).
  28. practicalswift force-pushed on Mar 12, 2018
  29. practicalswift force-pushed on Mar 12, 2018
  30. practicalswift commented at 4:02 pm on March 12, 2018: contributor
    Please re-review :-)
  31. practicalswift force-pushed on Mar 14, 2018
  32. practicalswift commented at 7:12 pm on March 14, 2018: contributor

    Rebased!

    Having this merged would have catched this locking incident: https://github.com/bitcoin/bitcoin/pull/12565/files#r171235800

    Reviews welcome! Perhaps @promag or @Sjors could take a look? :-)

  33. in src/wallet/wallet.cpp:1841 in b0cf4aec4d outdated
    1836@@ -1837,7 +1837,10 @@ std::set<uint256> CWalletTx::GetConflicts() const
    1837     if (pwallet != nullptr)
    1838     {
    1839         uint256 myHash = GetHash();
    1840-        result = pwallet->GetConflicts(myHash);
    1841+        {
    1842+            LOCK(pwallet->cs_wallet);
    


    promag commented at 9:20 pm on March 14, 2018:
    I believe this lock is not necessary, all callers have the lock already.
  34. Sjors commented at 10:17 pm on March 14, 2018: member
    Concept ACK: anything that prevents me from making mistakes :-)
  35. practicalswift force-pushed on Mar 14, 2018
  36. practicalswift commented at 10:48 pm on March 14, 2018: contributor
    @promag Thanks for reviewing. Feedback addressed. Please re-review :-)
  37. in src/wallet/wallet.cpp:1966 in ce156e6653 outdated
    1934@@ -1935,6 +1935,7 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
    1935 
    1936     CAmount nCredit = 0;
    1937     uint256 hashTx = GetHash();
    1938+    LOCK(pwallet->cs_wallet);
    


    promag commented at 11:41 pm on March 14, 2018:
    Unnecessary, callers of GetAvailableCredit already have the lock.

    practicalswift commented at 7:03 am on March 15, 2018:
    Is pcoin->pwallet->cs_wallet == pwallet->cs_wallet guaranteed?

    promag commented at 12:02 pm on March 15, 2018:
    Yes, otherwise we have a big problem I think 😛

    practicalswift commented at 2:08 pm on March 15, 2018:
    Unfortunately Clang’s thread-safety analysis does not seem to understand that :-(

    practicalswift commented at 7:51 am on March 19, 2018:
    @promag I think I’m unable to resolve this. Are you able to make this work with EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) on CWalletTx::GetAvailableCredit when compiling with Clang’s thread-safety analysis enabled?

    MarcoFalke commented at 1:10 pm on August 13, 2018:
    Agree with @promag . We wouldn’t want to add LOCKs just to please a static analyser that isn’t smart enough to figure out the lock is already taken.
  38. in src/wallet/wallet.cpp:1990 in ce156e6653 outdated
    1978@@ -1978,6 +1979,7 @@ CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool fUseCache) const
    1979         return nAvailableWatchCreditCached;
    1980 
    1981     CAmount nCredit = 0;
    1982+    LOCK(pwallet->cs_wallet);
    


    promag commented at 11:42 pm on March 14, 2018:
    Unnecessary, callers of GetAvailableWatchOnlyCredit already have the lock.

    practicalswift commented at 7:52 am on March 19, 2018:
    @promag See above. In theory you’re right, but I’ve been unable to convince Clang’s thread-safety analysis that so is the case in practice. See comment above. I might need some help here :-)
  39. sipa commented at 0:49 am on March 15, 2018: member
    Concept ACK
  40. practicalswift force-pushed on Mar 23, 2018
  41. practicalswift force-pushed on Mar 29, 2018
  42. practicalswift force-pushed on Apr 9, 2018
  43. practicalswift force-pushed on Apr 9, 2018
  44. practicalswift commented at 1:22 pm on April 9, 2018: contributor
    Rebased!
  45. in src/wallet/wallet.h:711 in 83d2186da4 outdated
    707@@ -708,7 +708,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
    708     int64_t m_max_keypool_index = 0;
    709     std::map<CKeyID, int64_t> m_pool_key_to_index;
    710 
    711-    int64_t nTimeFirstKey = 0;
    712+    int64_t nTimeFirstKey GUARDED_BY(cs_wallet);
    


    MarcoFalke commented at 1:24 pm on April 9, 2018:
    Why remove the initialization?

    practicalswift commented at 1:36 pm on April 9, 2018:
    Ouch, that was not the intention. Now fixed. Thanks for noticing. Please re-review.
  46. practicalswift force-pushed on Apr 9, 2018
  47. practicalswift force-pushed on Apr 9, 2018
  48. practicalswift commented at 10:58 pm on April 9, 2018: contributor
    Rebased!
  49. practicalswift force-pushed on May 5, 2018
  50. in src/wallet/wallet.cpp:322 in 0c6f50067d outdated
    318@@ -319,7 +319,7 @@ bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigne
    319  * Update wallet first key creation time. This should be called whenever keys
    320  * are added to the wallet, with the oldest key creation time.
    321  */
    322-void CWallet::UpdateTimeFirstKey(int64_t nCreateTime)
    323+void CWallet::UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
    


    MarcoFalke commented at 11:39 pm on May 29, 2018:
    All those are redundant to the header
  51. practicalswift force-pushed on Jun 3, 2018
  52. practicalswift force-pushed on Jun 3, 2018
  53. practicalswift commented at 7:41 am on June 3, 2018: contributor
    @MarcoFalke Thanks for the review. I’ve now reworked this PR and moved annotations to the .h files where possible. Could you please re-review? :-)
  54. MarcoFalke commented at 5:18 pm on June 3, 2018: member

    GetConflicts has still an annotation in the cpp file?

    • If it is not trivially possible to move to the header file, better remove the annotation for now.
  55. practicalswift commented at 5:34 pm on June 3, 2018: contributor

    @MarcoFalke

    Applying …

     0diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
     1index a74efb919..f2926fd74 100644
     2--- a/src/wallet/wallet.cpp
     3+++ b/src/wallet/wallet.cpp
     4@@ -1865,7 +1865,7 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman)
     5     return false;
     6 }
     7
     8-std::set<uint256> CWalletTx::GetConflicts() const EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
     9+std::set<uint256> CWalletTx::GetConflicts() const
    10 {
    11     std::set<uint256> result;
    12     if (pwallet != nullptr)
    13diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
    14index d1ffcfbdc..fa4ca5ccb 100644
    15--- a/src/wallet/wallet.h
    16+++ b/src/wallet/wallet.h
    17@@ -493,7 +493,7 @@ public:
    18     /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */
    19     bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state);
    20
    21-    std::set<uint256> GetConflicts() const;
    22+    std::set<uint256> GetConflicts() const EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet);
    23 };
    24
    25 class COutput
    

    … results in …

    0In file included from wallet/feebumper.cpp:6:
    1In file included from ./wallet/coincontrol.h:11:
    2./wallet/wallet.h:496:76: error: member access into incomplete type 'const CWallet'
    3    std::set<uint256> GetConflicts() const EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet);
    4                                                                           ^
    

    OTOH, applying only …

     0diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
     1index a74efb919..f2926fd74 100644
     2--- a/src/wallet/wallet.cpp
     3+++ b/src/wallet/wallet.cpp
     4@@ -1865,7 +1865,7 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman)
     5     return false;
     6 }
     7
     8-std::set<uint256> CWalletTx::GetConflicts() const EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
     9+std::set<uint256> CWalletTx::GetConflicts() const
    10 {
    11     std::set<uint256> result;
    12     if (pwallet != nullptr)
    

    … results in …

    0wallet/wallet.cpp:1874:27: error: calling function 'GetConflicts' requires holding mutex 'pwallet->cs_wallet' exclusively [-Werror,-Wthread-safety-analysis]
    1        result = pwallet->GetConflicts(myHash);
    2                          ^
    
  56. practicalswift commented at 12:53 pm on June 6, 2018: contributor

    @MarcoFalke Another alternative could be to add NO_THREAD_SAFETY_ANALYSIS here to disable the analysis locally.

    What would you suggest as the recommended way to proceed?

  57. MarcoFalke commented at 1:11 pm on June 6, 2018: member
    @practicalswift I like your latest suggestion (NO_THREAD_SAFETY_ANALYSIS). Make sure to include a comment to explain this is only temporary. Also, explain that this is safe to do, since we have a run-time AssertLockHeld in place.
  58. practicalswift force-pushed on Jun 6, 2018
  59. practicalswift force-pushed on Jun 6, 2018
  60. practicalswift force-pushed on Jun 6, 2018
  61. practicalswift force-pushed on Jun 6, 2018
  62. practicalswift force-pushed on Jun 6, 2018
  63. practicalswift commented at 3:16 pm on June 6, 2018: contributor
    @MarcoFalke Good point! Added and documented NO_THREAD_SAFETY_ANALYSIS. Please review :-)
  64. practicalswift force-pushed on Jul 11, 2018
  65. practicalswift commented at 11:33 pm on July 11, 2018: contributor
    Rebased!
  66. DrahtBot added the label Needs rebase on Jul 14, 2018
  67. practicalswift force-pushed on Jul 15, 2018
  68. practicalswift force-pushed on Jul 15, 2018
  69. practicalswift commented at 7:53 am on July 16, 2018: contributor
    Rebased!
  70. DrahtBot removed the label Needs rebase on Jul 16, 2018
  71. practicalswift force-pushed on Jul 20, 2018
  72. DrahtBot added the label Needs rebase on Jul 24, 2018
  73. practicalswift force-pushed on Aug 1, 2018
  74. practicalswift commented at 8:33 am on August 1, 2018: contributor
    Rebased!
  75. DrahtBot removed the label Needs rebase on Aug 1, 2018
  76. practicalswift force-pushed on Aug 6, 2018
  77. practicalswift commented at 4:16 pm on August 6, 2018: contributor
    Rebased!
  78. practicalswift force-pushed on Aug 13, 2018
  79. practicalswift commented at 10:47 am on August 13, 2018: contributor
    Rebase number eight performed! :-)
  80. practicalswift force-pushed on Aug 25, 2018
  81. practicalswift commented at 10:44 pm on August 25, 2018: contributor
    Rebased!
  82. practicalswift force-pushed on Aug 26, 2018
  83. practicalswift force-pushed on Aug 26, 2018
  84. practicalswift force-pushed on Aug 26, 2018
  85. practicalswift commented at 3:41 pm on August 26, 2018: contributor
    @TheBlueMatt @promag Feedback addressed (added two commits to keep changes easy to review). @MarcoFalke @sipa @Sjors Please re-review :-)
  86. MarcoFalke commented at 4:10 pm on August 26, 2018: member
    @practicalswift Could squash into two commits? First one is adding the LOCKs, the second one the annotations?
  87. practicalswift force-pushed on Aug 26, 2018
  88. practicalswift force-pushed on Aug 26, 2018
  89. practicalswift force-pushed on Aug 26, 2018
  90. practicalswift commented at 7:52 pm on August 26, 2018: contributor
    @MarcoFalke Done! Please re-review :-)
  91. MarcoFalke commented at 2:04 am on August 27, 2018: member
    utACK 75cb9c068570ec433f6ebc966f0771caa92efe81
  92. practicalswift force-pushed on Aug 30, 2018
  93. practicalswift commented at 2:57 pm on August 30, 2018: contributor
    Rebased! @MarcoFalke @promag - please re-review your utACK:s :-)
  94. DrahtBot commented at 1:30 pm on September 21, 2018: member
    • #14498 (rpcwallet: listsentbyaddress RPC by mrwhythat)
    • #14437 (Refactor: Start to separate wallet from node by ryanofsky)
    • #14144 (Refactoring: Clarify code using encrypted_batch in CWallet by domob1812)
    • #13756 (wallet: -avoidreuse feature for improved privacy by kallewoof)
    • #9381 (Remove CWalletTx merging logic from AddToWallet by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  95. wallet: Add missing locks 1c7e25db0c
  96. wallet: Add Clang thread safety analysis annotations dee42927c9
  97. Add GUARDED_BY(cs_wallet) for encrypted_batch, nWalletMaxVersion, m_max_keypool_index and nOrderPosNext
    * AddKeyPubKeyWithDB(...) reads encrypted_batch which potentially races with write in the same method.
    * IncOrderPosNext(...) reads nOrderPosNext which potentially races with write in BlockDisconnected(...).
    * LoadKeyPool(...) reads m_max_keypool_index which potentially races with write in BlockDisconnected(...).
    * LoadMinVersion(...) reads nWalletMaxVersion which potentially races with write in BlockDisconnected(...).
    37b2538c2d
  98. practicalswift force-pushed on Oct 9, 2018
  99. practicalswift commented at 10:19 am on October 9, 2018: contributor

    Updated!

    Added GUARDED_BY(cs_wallet) annotations also for encrypted_batch, nWalletMaxVersion, m_max_keypool_index and nOrderPosNext.

    Rationale:

    • AddKeyPubKeyWithDB(...) reads encrypted_batch which potentially races with write in the same method
    • IncOrderPosNext(...) reads nOrderPosNext which potentially races with write in BlockDisconnected(...)
    • LoadKeyPool(...) reads m_max_keypool_index which potentially races with write in BlockDisconnected(...)
    • LoadMinVersion(...) reads nWalletMaxVersion which potentially races with write in BlockDisconnected(...)

    Please review :-)

  100. practicalswift commented at 12:00 pm on October 9, 2018: contributor

    Added GUARDED_BY(cs_wallet) for setExternalKeyPool, mapKeyMetadata, m_script_metadata and setLockedCoins.

    Rationale:

    0$ git grep -E 'AssertLockHeld.*(setExternalKeyPool|mapKeyMetadata|m_script_metadata|setLockedCoins)' | sort | uniq -c
    1      4 src/wallet/wallet.cpp:    AssertLockHeld(cs_wallet); // mapKeyMetadata
    2      1 src/wallet/wallet.cpp:    AssertLockHeld(cs_wallet); // m_script_metadata
    3      1 src/wallet/wallet.cpp:    AssertLockHeld(cs_wallet); // setExternalKeyPool
    4      5 src/wallet/wallet.cpp:    AssertLockHeld(cs_wallet); // setLockedCoins
    
  101. Add GUARDED_BY(cs_wallet) for setExternalKeyPool, mapKeyMetadata, m_script_metadata and setLockedCoins 69e7ee2dd8
  102. practicalswift force-pushed on Oct 9, 2018
  103. practicalswift commented at 8:35 am on October 24, 2018: contributor
    @MarcoFalke @promag @TheBlueMatt Would you mind reviewing the updated version? :-)
  104. MarcoFalke commented at 8:52 am on October 24, 2018: member
    utACK 69e7ee2dd8173597e766262fd9a8caae569ddf5e
  105. MarcoFalke referenced this in commit e895fdc9fc on Oct 24, 2018
  106. MarcoFalke merged this on Oct 24, 2018
  107. MarcoFalke closed this on Oct 24, 2018

  108. in src/wallet/wallet.cpp:4096 in 69e7ee2dd8
    4092@@ -4093,7 +4093,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
    4093     // Try to top up keypool. No-op if the wallet is locked.
    4094     walletInstance->TopUpKeyPool();
    4095 
    4096-    LOCK(cs_main);
    4097+    LOCK2(cs_main, walletInstance->cs_wallet);
    


    promag commented at 9:03 am on October 24, 2018:
    No annotation requires this lock right?

    practicalswift commented at 9:28 am on October 24, 2018:

    Both cs_main and walletInstance->cs_wallet are required from what I can tell.

    Removing that lock results in the following:

     0wallet/wallet.cpp:4104:28: error: calling function 'FindForkInGlobalIndex' requires holding mutex 'cs_main' exclusively [-Werror,-Wthread-safety-analysis]
     1            pindexRescan = FindForkInGlobalIndex(chainActive, locator);
     2                           ^
     3wallet/wallet.cpp:4131:48: error: reading variable 'nTimeFirstKey' requires holding mutex 'walletInstance->cs_wallet' [-Werror,-Wthread-safety-analysis]
     4        while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) {
     5                                               ^
     6wallet/wallet.cpp:4131:114: error: reading variable 'nTimeFirstKey' requires holding mutex 'walletInstance->cs_wallet' [-Werror,-Wthread-safety-analysis]
     7        while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) {
     8                                                                                                                 ^
     9wallet/wallet.cpp:4156:77: error: reading variable 'mapWallet' requires holding mutex 'walletInstance->cs_wallet' [-Werror,-Wthread-safety-analysis]
    10                std::map<uint256, CWalletTx>::iterator mi = walletInstance->mapWallet.find(hash);
    11                                                                            ^
    12wallet/wallet.cpp:4157:43: error: reading variable 'mapWallet' requires holding mutex 'walletInstance->cs_wallet' [-Werror,-Wthread-safety-analysis]
    13                if (mi != walletInstance->mapWallet.end())
    14                                          ^
    15wallet/wallet.cpp:4181:90: error: calling function 'GetKeyPoolSize' requires holding mutex 'walletInstance->cs_wallet' exclusively [-Werror,-Wthread-safety-analysis]
    16        walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n",      walletInstance->GetKeyPoolSize());
    17                                                                                         ^
    18wallet/wallet.cpp:4182:90: error: reading variable 'mapWallet' requires holding mutex 'walletInstance->cs_wallet' [-Werror,-Wthread-safety-analysis]
    19        walletInstance->WalletLogPrintf("mapWallet.size() = %u\n",       walletInstance->mapWallet.size());
    20                                                                                         ^
    

    promag commented at 9:37 am on October 24, 2018:

    Right, the new annotations..

    It could make sense to avoid calling uiInterface.LoadWallet() with the lock held.


    practicalswift commented at 9:56 am on October 24, 2018:

    @promag Ah, now I follow. Suggested fix below. What do you think?

     0diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
     1index 29014790e..2deeb9c42 100644
     2--- a/src/wallet/wallet.cpp
     3+++ b/src/wallet/wallet.cpp
     4@@ -4093,7 +4093,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
     5     // Try to top up keypool. No-op if the wallet is locked.
     6     walletInstance->TopUpKeyPool();
     7
     8-    LOCK2(cs_main, walletInstance->cs_wallet);
     9+    LOCK(cs_main);
    10
    11     CBlockIndex *pindexRescan = chainActive.Genesis();
    12     if (!gArgs.GetBoolArg("-rescan", false))
    13@@ -4128,6 +4128,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
    14
    15         // No need to read and scan block if block was created before
    16         // our wallet birthday (as adjusted for block time variability)
    17+        LOCK(walletInstance->cs_wallet);
    18         while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) {
    19             pindexRescan = chainActive.Next(pindexRescan);
    20         }
    21@@ -4178,6 +4179,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
    22     walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
    23
    24     {
    25+        LOCK(walletInstance->cs_wallet);
    26         walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n",      walletInstance->GetKeyPoolSize());
    27         walletInstance->WalletLogPrintf("mapWallet.size() = %u\n",       walletInstance->mapWallet.size());
    28         walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n",  walletInstance->mapAddressBook.size());
    

    promag commented at 10:08 am on October 24, 2018:
    I think that currently there is no harm in calling uiInterface.LoadWallet() with the lock held but if it’s not necessary then I wouldn’t change that. The diff looks ok.
  109. promag commented at 9:09 am on October 24, 2018: member
    utACK 69e7ee2.
  110. LarryRuane referenced this in commit e1c6c472e9 on Apr 5, 2021
  111. LarryRuane referenced this in commit d5439c7386 on Apr 5, 2021
  112. LarryRuane referenced this in commit affdf23507 on Apr 5, 2021
  113. LarryRuane referenced this in commit ed497c99af on Apr 5, 2021
  114. practicalswift deleted the branch on Apr 10, 2021
  115. LarryRuane referenced this in commit b2cdcd07c1 on Apr 29, 2021
  116. LarryRuane referenced this in commit a0df9acb00 on Apr 29, 2021
  117. LarryRuane referenced this in commit 10f07f2ad1 on Apr 29, 2021
  118. LarryRuane referenced this in commit 973d009148 on Apr 29, 2021
  119. LarryRuane referenced this in commit 20ce9cce7e on Jun 1, 2021
  120. LarryRuane referenced this in commit 12a307c6e1 on Jun 1, 2021
  121. LarryRuane referenced this in commit 96b1669b6d on Jun 1, 2021
  122. LarryRuane referenced this in commit 4bae811116 on Jun 1, 2021
  123. PastaPastaPasta referenced this in commit dab5cfb8ca on Jul 17, 2021
  124. gades referenced this in commit a188a9ea87 on May 31, 2022
  125. DrahtBot locked this on Nov 22, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-03 10:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me