Browse Source

Merge pull request #3401

012ca1c LoadWallet: acquire cs_wallet mutex before clearing setKeyPool (Wladimir J. van der Laan)
9569168 Document cs_wallet lock and add AssertLockHeld (Wladimir J. van der Laan)
19a5676 Use mutex pointer instead of name for AssertLockHeld (Wladimir J. van der Laan)
metaverse
Wladimir J. van der Laan 11 years ago
parent
commit
7aedb91476
No known key found for this signature in database GPG Key ID: 74810B012346C9A6
  1. 2
      src/main.cpp
  2. 6
      src/sync.cpp
  3. 5
      src/sync.h
  4. 18
      src/wallet.cpp
  5. 13
      src/wallet.h

2
src/main.cpp

@ -2235,7 +2235,7 @@ void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
{
AssertLockHeld("cs_main");
AssertLockHeld(cs_main);
// Check for duplicate
uint256 hash = pblock->GetHash();

6
src/sync.cpp

@ -136,11 +136,11 @@ std::string LocksHeld()
return result;
}
void AssertLockHeld(std::string strName)
void AssertLockHeldInternal(const char *pszName, const char* pszFile, int nLine, void *cs)
{
BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack)
if (i.second.MutexName() == strName) return;
LogPrintf("Lock %s not held; locks held:\n%s", strName.c_str(), LocksHeld().c_str());
if (i.first == cs) return;
LogPrintf("Lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
assert(0);
}

5
src/sync.h

@ -88,12 +88,13 @@ typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
std::string LocksHeld();
void AssertLockHeld(std::string strName);
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs);
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
void static inline AssertLockHeld(std::string) {}
void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs) {}
#endif
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine);

18
src/wallet.cpp

@ -35,6 +35,7 @@ struct CompareValueOnly
CPubKey CWallet::GenerateNewKey()
{
AssertLockHeld(cs_wallet); // mapKeyMetadata
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
RandAddSeedPerfmon();
@ -60,6 +61,7 @@ CPubKey CWallet::GenerateNewKey()
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
{
AssertLockHeld(cs_wallet); // mapKeyMetadata
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false;
if (!fFileBacked)
@ -95,6 +97,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
{
AssertLockHeld(cs_wallet); // mapKeyMetadata
if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
nTimeFirstKey = meta.nCreateTime;
@ -202,6 +205,7 @@ public:
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
{
AssertLockHeld(cs_wallet); // nWalletVersion
if (nWalletVersion >= nVersion)
return true;
@ -235,6 +239,7 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn,
bool CWallet::SetMaxVersion(int nVersion)
{
AssertLockHeld(cs_wallet); // nWalletVersion, nWalletMaxVersion
// cannot downgrade below current version
if (nWalletVersion > nVersion)
return false;
@ -327,6 +332,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
{
AssertLockHeld(cs_wallet); // nOrderPosNext
int64_t nRet = nOrderPosNext++;
if (pwalletdb) {
pwalletdb->WriteOrderPosNext(nOrderPosNext);
@ -338,6 +344,7 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
{
AssertLockHeld(cs_wallet); // mapWallet
CWalletDB walletdb(strWalletFile);
// First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
@ -1492,6 +1499,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
if (CDB::Rewrite(strWalletFile, "\x04pool"))
{
LOCK(cs_wallet);
setKeyPool.clear();
// Note: can't top-up keypool here, because wallet is locked.
// User will be prompted to unlock wallet the next operation
@ -1509,6 +1517,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
{
AssertLockHeld(cs_wallet); // mapAddressBook
std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
mapAddressBook[address].name = strName;
if (!strPurpose.empty()) /* update purpose only if requested */
@ -1525,6 +1534,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
bool CWallet::DelAddressBook(const CTxDestination& address)
{
AssertLockHeld(cs_wallet); // mapAddressBook
mapAddressBook.erase(address);
NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
if (!fFileBacked)
@ -1738,6 +1748,7 @@ std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
set< set<CTxDestination> > CWallet::GetAddressGroupings()
{
AssertLockHeld(cs_wallet); // mapWallet
set< set<CTxDestination> > groupings;
set<CTxDestination> grouping;
@ -1830,6 +1841,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
{
AssertLockHeld(cs_wallet); // mapWallet
set<CTxDestination> result;
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
{
@ -1911,21 +1923,25 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx)
void CWallet::LockCoin(COutPoint& output)
{
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.insert(output);
}
void CWallet::UnlockCoin(COutPoint& output)
{
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.erase(output);
}
void CWallet::UnlockAllCoins()
{
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.clear();
}
bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
{
AssertLockHeld(cs_wallet); // setLockedCoins
COutPoint outpt(hash, n);
return (setLockedCoins.count(outpt) > 0);
@ -1933,6 +1949,7 @@ bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
{
AssertLockHeld(cs_wallet); // setLockedCoins
for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
it != setLockedCoins.end(); it++) {
COutPoint outpt = (*it);
@ -1941,6 +1958,7 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
}
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
AssertLockHeld(cs_wallet); // mapKeyMetadata
mapKeyBirth.clear();
// get birth times for keys with metadata

13
src/wallet.h

@ -105,6 +105,11 @@ private:
int64_t nLastResend;
public:
/// Main wallet lock.
/// This lock protects all the fields added by CWallet
/// except for:
/// fFileBacked (immutable after instantiation)
/// strWalletFile (immutable after instantiation)
mutable CCriticalSection cs_wallet;
bool fFileBacked;
@ -154,10 +159,11 @@ public:
int64_t nTimeFirstKey;
// check whether we are allowed to upgrade (or already support) to the named feature
bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const;
bool SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const;
void LockCoin(COutPoint& output);
void UnlockCoin(COutPoint& output);
@ -174,7 +180,7 @@ public:
// Load metadata (used by LoadWallet)
bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
// Adds an encrypted key to the store, and saves it to disk.
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
@ -323,6 +329,7 @@ public:
unsigned int GetKeyPoolSize()
{
AssertLockHeld(cs_wallet); // setKeyPool
return setKeyPool.size();
}
@ -335,7 +342,7 @@ public:
bool SetMaxVersion(int nVersion);
// get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetVersion() { return nWalletVersion; }
int GetVersion() { AssertLockHeld(cs_wallet); return nWalletVersion; }
/** Address book entry changed.
* @note called with lock cs_wallet held.

Loading…
Cancel
Save