Merge pull request #1052 from sipa/scopedlocks

Use scoped locks instead of CRITICAL_BLOCK
This commit is contained in:
Pieter Wuille 2012-04-09 13:25:17 -07:00
commit 1a275bac2b
19 changed files with 300 additions and 204 deletions

View file

@ -266,8 +266,8 @@ public:
// //
// This format is more complex, but significantly smaller (at most 1.5 MiB), and supports // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
// changes to the ADDRMAN_ parameters without breaking the on-disk structure. // changes to the ADDRMAN_ parameters without breaking the on-disk structure.
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
unsigned char nVersion = 0; unsigned char nVersion = 0;
READWRITE(nVersion); READWRITE(nVersion);
READWRITE(nKey); READWRITE(nKey);
@ -398,8 +398,8 @@ public:
void Check() void Check()
{ {
#ifdef DEBUG_ADDRMAN #ifdef DEBUG_ADDRMAN
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
int err; int err;
if ((err=Check_())) if ((err=Check_()))
printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err); printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
@ -411,8 +411,8 @@ public:
bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0) bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0)
{ {
bool fRet = false; bool fRet = false;
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
Check(); Check();
fRet |= Add_(addr, source, nTimePenalty); fRet |= Add_(addr, source, nTimePenalty);
Check(); Check();
@ -426,8 +426,8 @@ public:
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0) bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0)
{ {
int nAdd = 0; int nAdd = 0;
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
Check(); Check();
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0; nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
@ -441,8 +441,8 @@ public:
// Mark an entry as accessible. // Mark an entry as accessible.
void Good(const CService &addr, int64 nTime = GetAdjustedTime()) void Good(const CService &addr, int64 nTime = GetAdjustedTime())
{ {
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
Check(); Check();
Good_(addr, nTime); Good_(addr, nTime);
Check(); Check();
@ -452,8 +452,8 @@ public:
// Mark an entry as connection attempted to. // Mark an entry as connection attempted to.
void Attempt(const CService &addr, int64 nTime = GetAdjustedTime()) void Attempt(const CService &addr, int64 nTime = GetAdjustedTime())
{ {
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
Check(); Check();
Attempt_(addr, nTime); Attempt_(addr, nTime);
Check(); Check();
@ -465,8 +465,8 @@ public:
CAddress Select(int nUnkBias = 50) CAddress Select(int nUnkBias = 50)
{ {
CAddress addrRet; CAddress addrRet;
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
Check(); Check();
addrRet = Select_(nUnkBias); addrRet = Select_(nUnkBias);
Check(); Check();
@ -479,8 +479,10 @@ public:
{ {
Check(); Check();
std::vector<CAddress> vAddr; std::vector<CAddress> vAddr;
CRITICAL_BLOCK(cs) {
LOCK(cs);
GetAddr_(vAddr); GetAddr_(vAddr);
}
Check(); Check();
return vAddr; return vAddr;
} }
@ -488,8 +490,8 @@ public:
// Mark an entry as currently-connected-to. // Mark an entry as currently-connected-to.
void Connected(const CService &addr, int64 nTime = GetAdjustedTime()) void Connected(const CService &addr, int64 nTime = GetAdjustedTime())
{ {
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
Check(); Check();
Connected_(addr, nTime); Connected_(addr, nTime);
Check(); Check();

View file

@ -1647,8 +1647,8 @@ Value walletlock(const Array& params, bool fHelp)
if (!pwalletMain->IsCrypted()) if (!pwalletMain->IsCrypted())
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called."); throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
CRITICAL_BLOCK(cs_nWalletUnlockTime)
{ {
LOCK(cs_nWalletUnlockTime);
pwalletMain->Lock(); pwalletMain->Lock();
nWalletUnlockTime = 0; nWalletUnlockTime = 0;
} }
@ -2500,9 +2500,10 @@ void ThreadRPCServer2(void* parg)
{ {
// Execute // Execute
Value result; Value result;
CRITICAL_BLOCK(cs_main) {
CRITICAL_BLOCK(pwalletMain->cs_wallet) LOCK2(cs_main, pwalletMain->cs_wallet);
result = (*(*mi).second)(params, false); result = (*(*mi).second)(params, false);
}
// Send reply // Send reply
string strReply = JSONRPCReply(result, Value::null, id); string strReply = JSONRPCReply(result, Value::null, id);

View file

@ -72,8 +72,8 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
if (fCreate) if (fCreate)
nFlags |= DB_CREATE; nFlags |= DB_CREATE;
CRITICAL_BLOCK(cs_db)
{ {
LOCK(cs_db);
if (!fDbEnvInit) if (!fDbEnvInit)
{ {
if (fShutdown) if (fShutdown)
@ -128,8 +128,10 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
{ {
delete pdb; delete pdb;
pdb = NULL; pdb = NULL;
CRITICAL_BLOCK(cs_db) {
LOCK(cs_db);
--mapFileUseCount[strFile]; --mapFileUseCount[strFile];
}
strFile = ""; strFile = "";
throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret)); throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret));
} }
@ -167,14 +169,16 @@ void CDB::Close()
dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0); dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
CRITICAL_BLOCK(cs_db) {
LOCK(cs_db);
--mapFileUseCount[strFile]; --mapFileUseCount[strFile];
}
} }
void static CloseDb(const string& strFile) void static CloseDb(const string& strFile)
{ {
CRITICAL_BLOCK(cs_db)
{ {
LOCK(cs_db);
if (mapDb[strFile] != NULL) if (mapDb[strFile] != NULL)
{ {
// Close the database handle // Close the database handle
@ -190,8 +194,8 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
{ {
while (!fShutdown) while (!fShutdown)
{ {
CRITICAL_BLOCK(cs_db)
{ {
LOCK(cs_db);
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0) if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
{ {
// Flush log data to the dat file // Flush log data to the dat file
@ -288,8 +292,8 @@ void DBFlush(bool fShutdown)
printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started"); printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
if (!fDbEnvInit) if (!fDbEnvInit)
return; return;
CRITICAL_BLOCK(cs_db)
{ {
LOCK(cs_db);
map<string, int>::iterator mi = mapFileUseCount.begin(); map<string, int>::iterator mi = mapFileUseCount.begin();
while (mi != mapFileUseCount.end()) while (mi != mapFileUseCount.end())
{ {
@ -879,8 +883,8 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
bool fIsEncrypted = false; bool fIsEncrypted = false;
//// todo: shouldn't we catch exceptions and try to recover and continue? //// todo: shouldn't we catch exceptions and try to recover and continue?
CRITICAL_BLOCK(pwallet->cs_wallet)
{ {
LOCK(pwallet->cs_wallet);
int nMinVersion = 0; int nMinVersion = 0;
if (Read((string)"minversion", nMinVersion)) if (Read((string)"minversion", nMinVersion))
{ {
@ -1121,7 +1125,8 @@ void ThreadFlushWalletDB(void* parg)
if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2) if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
{ {
TRY_CRITICAL_BLOCK(cs_db) TRY_LOCK(cs_db,lockDb);
if (lockDb)
{ {
// Don't do this if any databases are in use // Don't do this if any databases are in use
int nRefCount = 0; int nRefCount = 0;
@ -1162,8 +1167,8 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
return false; return false;
while (!fShutdown) while (!fShutdown)
{ {
CRITICAL_BLOCK(cs_db)
{ {
LOCK(cs_db);
if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0) if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
{ {
// Flush log data to the dat file // Flush log data to the dat file

View file

@ -40,10 +40,13 @@ void Shutdown(void* parg)
static CCriticalSection cs_Shutdown; static CCriticalSection cs_Shutdown;
static bool fTaken; static bool fTaken;
bool fFirstThread = false; bool fFirstThread = false;
TRY_CRITICAL_BLOCK(cs_Shutdown)
{ {
fFirstThread = !fTaken; TRY_LOCK(cs_Shutdown, lockShutdown);
fTaken = true; if (lockShutdown)
{
fFirstThread = !fTaken;
fTaken = true;
}
} }
static bool fExit; static bool fExit;
if (fFirstThread) if (fFirstThread)

View file

@ -21,31 +21,37 @@ bool CBasicKeyStore::AddKey(const CKey& key)
{ {
bool fCompressed = false; bool fCompressed = false;
CSecret secret = key.GetSecret(fCompressed); CSecret secret = key.GetSecret(fCompressed);
CRITICAL_BLOCK(cs_KeyStore) {
LOCK(cs_KeyStore);
mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed); mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
}
return true; return true;
} }
bool CBasicKeyStore::AddCScript(const CScript& redeemScript) bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
{ {
CRITICAL_BLOCK(cs_KeyStore) {
LOCK(cs_KeyStore);
mapScripts[Hash160(redeemScript)] = redeemScript; mapScripts[Hash160(redeemScript)] = redeemScript;
}
return true; return true;
} }
bool CBasicKeyStore::HaveCScript(const uint160& hash) const bool CBasicKeyStore::HaveCScript(const uint160& hash) const
{ {
bool result; bool result;
CRITICAL_BLOCK(cs_KeyStore) {
LOCK(cs_KeyStore);
result = (mapScripts.count(hash) > 0); result = (mapScripts.count(hash) > 0);
}
return result; return result;
} }
bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
ScriptMap::const_iterator mi = mapScripts.find(hash); ScriptMap::const_iterator mi = mapScripts.find(hash);
if (mi != mapScripts.end()) if (mi != mapScripts.end())
{ {
@ -58,8 +64,8 @@ bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) c
bool CCryptoKeyStore::SetCrypted() bool CCryptoKeyStore::SetCrypted()
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (fUseCrypto) if (fUseCrypto)
return true; return true;
if (!mapKeys.empty()) if (!mapKeys.empty())
@ -71,8 +77,8 @@ bool CCryptoKeyStore::SetCrypted()
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (!SetCrypted()) if (!SetCrypted())
return false; return false;
@ -100,8 +106,8 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
bool CCryptoKeyStore::AddKey(const CKey& key) bool CCryptoKeyStore::AddKey(const CKey& key)
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (!IsCrypted()) if (!IsCrypted())
return CBasicKeyStore::AddKey(key); return CBasicKeyStore::AddKey(key);
@ -123,8 +129,8 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (!SetCrypted()) if (!SetCrypted())
return false; return false;
@ -135,8 +141,8 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey,
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (!IsCrypted()) if (!IsCrypted())
return CBasicKeyStore::GetKey(address, keyOut); return CBasicKeyStore::GetKey(address, keyOut);
@ -160,8 +166,8 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (!IsCrypted()) if (!IsCrypted())
return CKeyStore::GetPubKey(address, vchPubKeyOut); return CKeyStore::GetPubKey(address, vchPubKeyOut);
@ -177,8 +183,8 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsi
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (!mapCryptedKeys.empty() || IsCrypted()) if (!mapCryptedKeys.empty() || IsCrypted())
return false; return false;

View file

@ -54,15 +54,17 @@ public:
bool HaveKey(const CBitcoinAddress &address) const bool HaveKey(const CBitcoinAddress &address) const
{ {
bool result; bool result;
CRITICAL_BLOCK(cs_KeyStore) {
LOCK(cs_KeyStore);
result = (mapKeys.count(address) > 0); result = (mapKeys.count(address) > 0);
}
return result; return result;
} }
void GetKeys(std::set<CBitcoinAddress> &setAddress) const void GetKeys(std::set<CBitcoinAddress> &setAddress) const
{ {
setAddress.clear(); setAddress.clear();
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
KeyMap::const_iterator mi = mapKeys.begin(); KeyMap::const_iterator mi = mapKeys.begin();
while (mi != mapKeys.end()) while (mi != mapKeys.end())
{ {
@ -73,8 +75,8 @@ public:
} }
bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
KeyMap::const_iterator mi = mapKeys.find(address); KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end()) if (mi != mapKeys.end())
{ {
@ -129,8 +131,10 @@ public:
if (!IsCrypted()) if (!IsCrypted())
return false; return false;
bool result; bool result;
CRITICAL_BLOCK(cs_KeyStore) {
LOCK(cs_KeyStore);
result = vMasterKey.empty(); result = vMasterKey.empty();
}
return result; return result;
} }
@ -139,8 +143,10 @@ public:
if (!SetCrypted()) if (!SetCrypted())
return false; return false;
CRITICAL_BLOCK(cs_KeyStore) {
LOCK(cs_KeyStore);
vMasterKey.clear(); vMasterKey.clear();
}
return true; return true;
} }
@ -149,8 +155,8 @@ public:
bool AddKey(const CKey& key); bool AddKey(const CKey& key);
bool HaveKey(const CBitcoinAddress &address) const bool HaveKey(const CBitcoinAddress &address) const
{ {
CRITICAL_BLOCK(cs_KeyStore)
{ {
LOCK(cs_KeyStore);
if (!IsCrypted()) if (!IsCrypted())
return CBasicKeyStore::HaveKey(address); return CBasicKeyStore::HaveKey(address);
return mapCryptedKeys.count(address) > 0; return mapCryptedKeys.count(address) > 0;

View file

@ -75,16 +75,16 @@ int64 nTransactionFee = 0;
void RegisterWallet(CWallet* pwalletIn) void RegisterWallet(CWallet* pwalletIn)
{ {
CRITICAL_BLOCK(cs_setpwalletRegistered)
{ {
LOCK(cs_setpwalletRegistered);
setpwalletRegistered.insert(pwalletIn); setpwalletRegistered.insert(pwalletIn);
} }
} }
void UnregisterWallet(CWallet* pwalletIn) void UnregisterWallet(CWallet* pwalletIn)
{ {
CRITICAL_BLOCK(cs_setpwalletRegistered)
{ {
LOCK(cs_setpwalletRegistered);
setpwalletRegistered.erase(pwalletIn); setpwalletRegistered.erase(pwalletIn);
} }
} }
@ -478,9 +478,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
// Do we already have it? // Do we already have it?
uint256 hash = GetHash(); uint256 hash = GetHash();
CRITICAL_BLOCK(cs_mapTransactions) {
LOCK(cs_mapTransactions);
if (mapTransactions.count(hash)) if (mapTransactions.count(hash))
return false; return false;
}
if (fCheckInputs) if (fCheckInputs)
if (txdb.ContainsTx(hash)) if (txdb.ContainsTx(hash))
return false; return false;
@ -552,8 +554,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
static int64 nLastTime; static int64 nLastTime;
int64 nNow = GetTime(); int64 nNow = GetTime();
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
// Use an exponentially decaying ~10-minute window: // Use an exponentially decaying ~10-minute window:
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime)); dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
nLastTime = nNow; nLastTime = nNow;
@ -576,8 +578,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
} }
// Store transaction in memory // Store transaction in memory
CRITICAL_BLOCK(cs_mapTransactions)
{ {
LOCK(cs_mapTransactions);
if (ptxOld) if (ptxOld)
{ {
printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
@ -608,8 +610,8 @@ bool CTransaction::AddToMemoryPoolUnchecked()
printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mapTransactions.size()); printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mapTransactions.size());
// Add to memory pool without checking anything. Don't call this directly, // Add to memory pool without checking anything. Don't call this directly,
// call AcceptToMemoryPool to properly check the transaction first. // call AcceptToMemoryPool to properly check the transaction first.
CRITICAL_BLOCK(cs_mapTransactions)
{ {
LOCK(cs_mapTransactions);
uint256 hash = GetHash(); uint256 hash = GetHash();
mapTransactions[hash] = *this; mapTransactions[hash] = *this;
for (int i = 0; i < vin.size(); i++) for (int i = 0; i < vin.size(); i++)
@ -624,8 +626,8 @@ bool CTransaction::AddToMemoryPoolUnchecked()
bool CTransaction::RemoveFromMemoryPool() bool CTransaction::RemoveFromMemoryPool()
{ {
// Remove transaction from memory pool // Remove transaction from memory pool
CRITICAL_BLOCK(cs_mapTransactions)
{ {
LOCK(cs_mapTransactions);
uint256 hash = GetHash(); uint256 hash = GetHash();
if (mapTransactions.count(hash)) if (mapTransactions.count(hash))
{ {
@ -702,8 +704,9 @@ bool CMerkleTx::AcceptToMemoryPool()
bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs) bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
{ {
CRITICAL_BLOCK(cs_mapTransactions)
{ {
LOCK(cs_mapTransactions);
// Add previous supporting transactions first // Add previous supporting transactions first
BOOST_FOREACH(CMerkleTx& tx, vtxPrev) BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
{ {
@ -1024,8 +1027,8 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
if (!fFound || txindex.pos == CDiskTxPos(1,1,1)) if (!fFound || txindex.pos == CDiskTxPos(1,1,1))
{ {
// Get prev tx from single transactions in memory // Get prev tx from single transactions in memory
CRITICAL_BLOCK(cs_mapTransactions)
{ {
LOCK(cs_mapTransactions);
if (!mapTransactions.count(prevout.hash)) if (!mapTransactions.count(prevout.hash))
return error("FetchInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); return error("FetchInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
txPrev = mapTransactions[prevout.hash]; txPrev = mapTransactions[prevout.hash];
@ -1190,8 +1193,8 @@ bool CTransaction::ClientConnectInputs()
return false; return false;
// Take over previous transactions' spent pointers // Take over previous transactions' spent pointers
CRITICAL_BLOCK(cs_mapTransactions)
{ {
LOCK(cs_mapTransactions);
int64 nValueIn = 0; int64 nValueIn = 0;
for (int i = 0; i < vin.size(); i++) for (int i = 0; i < vin.size(); i++)
{ {
@ -1707,10 +1710,12 @@ bool CBlock::AcceptBlock()
// Relay inventory, but don't relay old inventory during initial block download // Relay inventory, but don't relay old inventory during initial block download
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
if (hashBestChain == hash) if (hashBestChain == hash)
CRITICAL_BLOCK(cs_vNodes) {
BOOST_FOREACH(CNode* pnode, vNodes) LOCK(cs_vNodes);
if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) BOOST_FOREACH(CNode* pnode, vNodes)
pnode->PushInventory(CInv(MSG_BLOCK, hash)); if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
pnode->PushInventory(CInv(MSG_BLOCK, hash));
}
return true; return true;
} }
@ -2052,8 +2057,8 @@ string GetWarnings(string strFor)
} }
// Alerts // Alerts
CRITICAL_BLOCK(cs_mapAlerts)
{ {
LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
{ {
const CAlert& alert = item.second; const CAlert& alert = item.second;
@ -2080,8 +2085,8 @@ bool CAlert::ProcessAlert()
if (!IsInEffect()) if (!IsInEffect())
return false; return false;
CRITICAL_BLOCK(cs_mapAlerts)
{ {
LOCK(cs_mapAlerts);
// Cancel previous alerts // Cancel previous alerts
for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
{ {
@ -2260,9 +2265,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
} }
// Relay alerts // Relay alerts
CRITICAL_BLOCK(cs_mapAlerts) {
LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
item.second.RelayTo(pfrom); item.second.RelayTo(pfrom);
}
pfrom->fSuccessfullyConnected = true; pfrom->fSuccessfullyConnected = true;
@ -2316,8 +2323,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{ {
// Relay to a limited number of other nodes // Relay to a limited number of other nodes
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
// Use deterministic randomness to send to the same nodes for 24 hours // Use deterministic randomness to send to the same nodes for 24 hours
// at a time so the setAddrKnowns of the chosen nodes prevent repeats // at a time so the setAddrKnowns of the chosen nodes prevent repeats
static uint256 hashSalt; static uint256 hashSalt;
@ -2428,8 +2435,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else if (inv.IsKnownType()) else if (inv.IsKnownType())
{ {
// Send stream from relay memory // Send stream from relay memory
CRITICAL_BLOCK(cs_mapRelay)
{ {
LOCK(cs_mapRelay);
map<CInv, CDataStream>::iterator mi = mapRelay.find(inv); map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
if (mi != mapRelay.end()) if (mi != mapRelay.end())
pfrom->PushMessage(inv.GetCommand(), (*mi).second); pfrom->PushMessage(inv.GetCommand(), (*mi).second);
@ -2634,8 +2641,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> hashReply; vRecv >> hashReply;
CRequestTracker tracker; CRequestTracker tracker;
CRITICAL_BLOCK(pfrom->cs_mapRequests)
{ {
LOCK(pfrom->cs_mapRequests);
map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply); map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
if (mi != pfrom->mapRequests.end()) if (mi != pfrom->mapRequests.end())
{ {
@ -2662,9 +2669,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{ {
// Relay // Relay
pfrom->setKnown.insert(alert.GetHash()); pfrom->setKnown.insert(alert.GetHash());
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
alert.RelayTo(pnode); alert.RelayTo(pnode);
}
} }
} }
@ -2763,8 +2772,10 @@ bool ProcessMessages(CNode* pfrom)
bool fRet = false; bool fRet = false;
try try
{ {
CRITICAL_BLOCK(cs_main) {
LOCK(cs_main);
fRet = ProcessMessage(pfrom, strCommand, vMsg); fRet = ProcessMessage(pfrom, strCommand, vMsg);
}
if (fShutdown) if (fShutdown)
return true; return true;
} }
@ -2802,8 +2813,8 @@ bool ProcessMessages(CNode* pfrom)
bool SendMessages(CNode* pto, bool fSendTrickle) bool SendMessages(CNode* pto, bool fSendTrickle)
{ {
CRITICAL_BLOCK(cs_main)
{ {
LOCK(cs_main);
// Don't send anything until we get their version message // Don't send anything until we get their version message
if (pto->nVersion == 0) if (pto->nVersion == 0)
return true; return true;
@ -2819,8 +2830,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
static int64 nLastRebroadcast; static int64 nLastRebroadcast;
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
{ {
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
{ {
// Periodically clear setAddrKnown to allow refresh broadcasts // Periodically clear setAddrKnown to allow refresh broadcasts
@ -2871,8 +2882,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// //
vector<CInv> vInv; vector<CInv> vInv;
vector<CInv> vInvWait; vector<CInv> vInvWait;
CRITICAL_BLOCK(pto->cs_inventory)
{ {
LOCK(pto->cs_inventory);
vInv.reserve(pto->vInventoryToSend.size()); vInv.reserve(pto->vInventoryToSend.size());
vInvWait.reserve(pto->vInventoryToSend.size()); vInvWait.reserve(pto->vInventoryToSend.size());
BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend) BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
@ -3087,9 +3098,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
// Collect memory pool transactions into the block // Collect memory pool transactions into the block
int64 nFees = 0; int64 nFees = 0;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapTransactions)
{ {
LOCK2(cs_main, cs_mapTransactions);
CTxDB txdb("r"); CTxDB txdb("r");
// Priority order to process transactions // Priority order to process transactions
@ -3317,8 +3327,8 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str()); printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
// Found a solution // Found a solution
CRITICAL_BLOCK(cs_main)
{ {
LOCK(cs_main);
if (pblock->hashPrevBlock != hashBestChain) if (pblock->hashPrevBlock != hashBestChain)
return error("BitcoinMiner : generated block is stale"); return error("BitcoinMiner : generated block is stale");
@ -3326,8 +3336,10 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
reservekey.KeepKey(); reservekey.KeepKey();
// Track how many getdata requests this block gets // Track how many getdata requests this block gets
CRITICAL_BLOCK(wallet.cs_wallet) {
LOCK(wallet.cs_wallet);
wallet.mapRequestCount[pblock->GetHash()] = 0; wallet.mapRequestCount[pblock->GetHash()] = 0;
}
// Process this block the same as if we had received it from another node // Process this block the same as if we had received it from another node
if (!ProcessBlock(NULL, pblock)) if (!ProcessBlock(NULL, pblock))
@ -3443,8 +3455,8 @@ void static BitcoinMiner(CWallet *pwallet)
if (GetTimeMillis() - nHPSTimerStart > 4000) if (GetTimeMillis() - nHPSTimerStart > 4000)
{ {
static CCriticalSection cs; static CCriticalSection cs;
CRITICAL_BLOCK(cs)
{ {
LOCK(cs);
if (GetTimeMillis() - nHPSTimerStart > 4000) if (GetTimeMillis() - nHPSTimerStart > 4000)
{ {
dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart); dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);

View file

@ -272,9 +272,11 @@ void ThreadGetMyExternalIP(void* parg)
// setAddrKnown automatically filters any duplicate sends. // setAddrKnown automatically filters any duplicate sends.
CAddress addr(addrLocalHost); CAddress addr(addrLocalHost);
addr.nTime = GetAdjustedTime(); addr.nTime = GetAdjustedTime();
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
pnode->PushAddress(addr); pnode->PushAddress(addr);
}
} }
} }
} }
@ -296,8 +298,8 @@ void AddressCurrentlyConnected(const CService& addr)
CNode* FindNode(const CNetAddr& ip) CNode* FindNode(const CNetAddr& ip)
{ {
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
if ((CNetAddr)pnode->addr == ip) if ((CNetAddr)pnode->addr == ip)
return (pnode); return (pnode);
@ -307,8 +309,8 @@ CNode* FindNode(const CNetAddr& ip)
CNode* FindNode(const CService& addr) CNode* FindNode(const CService& addr)
{ {
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
if ((CService)pnode->addr == addr) if ((CService)pnode->addr == addr)
return (pnode); return (pnode);
@ -362,10 +364,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
pnode->AddRef(nTimeout); pnode->AddRef(nTimeout);
else else
pnode->AddRef(); pnode->AddRef();
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
vNodes.push_back(pnode); vNodes.push_back(pnode);
WAITABLE_CRITICAL_BLOCK(csOutbound) }
{
WAITABLE_LOCK(csOutbound);
nOutbound++; nOutbound++;
}
pnode->nTimeConnected = GetTime(); pnode->nTimeConnected = GetTime();
return pnode; return pnode;
@ -421,8 +427,8 @@ void CNode::ClearBanned()
bool CNode::IsBanned(CNetAddr ip) bool CNode::IsBanned(CNetAddr ip)
{ {
bool fResult = false; bool fResult = false;
CRITICAL_BLOCK(cs_setBanned)
{ {
LOCK(cs_setBanned);
std::map<CNetAddr, int64>::iterator i = setBanned.find(ip); std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
if (i != setBanned.end()) if (i != setBanned.end())
{ {
@ -446,9 +452,11 @@ bool CNode::Misbehaving(int howmuch)
if (nMisbehavior >= GetArg("-banscore", 100)) if (nMisbehavior >= GetArg("-banscore", 100))
{ {
int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
CRITICAL_BLOCK(cs_setBanned) {
LOCK(cs_setBanned);
if (setBanned[addr] < banTime) if (setBanned[addr] < banTime)
setBanned[addr] = banTime; setBanned[addr] = banTime;
}
CloseSocketDisconnect(); CloseSocketDisconnect();
printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior); printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
return true; return true;
@ -497,8 +505,8 @@ void ThreadSocketHandler2(void* parg)
// //
// Disconnect nodes // Disconnect nodes
// //
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
// Disconnect unused nodes // Disconnect unused nodes
vector<CNode*> vNodesCopy = vNodes; vector<CNode*> vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy) BOOST_FOREACH(CNode* pnode, vNodesCopy)
@ -510,8 +518,8 @@ void ThreadSocketHandler2(void* parg)
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
if (!pnode->fInbound) if (!pnode->fInbound)
WAITABLE_CRITICAL_BLOCK(csOutbound)
{ {
WAITABLE_LOCK(csOutbound);
nOutbound--; nOutbound--;
// Connection slot(s) were removed, notify connection creator(s) // Connection slot(s) were removed, notify connection creator(s)
@ -538,11 +546,23 @@ void ThreadSocketHandler2(void* parg)
if (pnode->GetRefCount() <= 0) if (pnode->GetRefCount() <= 0)
{ {
bool fDelete = false; bool fDelete = false;
TRY_CRITICAL_BLOCK(pnode->cs_vSend) {
TRY_CRITICAL_BLOCK(pnode->cs_vRecv) TRY_LOCK(pnode->cs_vSend, lockSend);
TRY_CRITICAL_BLOCK(pnode->cs_mapRequests) if (lockSend)
TRY_CRITICAL_BLOCK(pnode->cs_inventory) {
fDelete = true; TRY_LOCK(pnode->cs_vRecv, lockRecv);
if (lockRecv)
{
TRY_LOCK(pnode->cs_mapRequests, lockReq);
if (lockReq)
{
TRY_LOCK(pnode->cs_inventory, lockInv);
if (lockInv)
fDelete = true;
}
}
}
}
if (fDelete) if (fDelete)
{ {
vNodesDisconnected.remove(pnode); vNodesDisconnected.remove(pnode);
@ -576,8 +596,8 @@ void ThreadSocketHandler2(void* parg)
if(hListenSocket != INVALID_SOCKET) if(hListenSocket != INVALID_SOCKET)
FD_SET(hListenSocket, &fdsetRecv); FD_SET(hListenSocket, &fdsetRecv);
hSocketMax = max(hSocketMax, hListenSocket); hSocketMax = max(hSocketMax, hListenSocket);
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
{ {
if (pnode->hSocket == INVALID_SOCKET) if (pnode->hSocket == INVALID_SOCKET)
@ -585,9 +605,11 @@ void ThreadSocketHandler2(void* parg)
FD_SET(pnode->hSocket, &fdsetRecv); FD_SET(pnode->hSocket, &fdsetRecv);
FD_SET(pnode->hSocket, &fdsetError); FD_SET(pnode->hSocket, &fdsetError);
hSocketMax = max(hSocketMax, pnode->hSocket); hSocketMax = max(hSocketMax, pnode->hSocket);
TRY_CRITICAL_BLOCK(pnode->cs_vSend) {
if (!pnode->vSend.empty()) TRY_LOCK(pnode->cs_vSend, lockSend);
if (lockSend && !pnode->vSend.empty())
FD_SET(pnode->hSocket, &fdsetSend); FD_SET(pnode->hSocket, &fdsetSend);
}
} }
} }
@ -625,10 +647,12 @@ void ThreadSocketHandler2(void* parg)
if (hSocket != INVALID_SOCKET) if (hSocket != INVALID_SOCKET)
addr = CAddress(sockaddr); addr = CAddress(sockaddr);
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
if (pnode->fInbound) if (pnode->fInbound)
nInbound++; nInbound++;
}
if (hSocket == INVALID_SOCKET) if (hSocket == INVALID_SOCKET)
{ {
@ -637,9 +661,11 @@ void ThreadSocketHandler2(void* parg)
} }
else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
{ {
CRITICAL_BLOCK(cs_setservAddNodeAddresses) {
LOCK(cs_setservAddNodeAddresses);
if (!setservAddNodeAddresses.count(addr)) if (!setservAddNodeAddresses.count(addr))
closesocket(hSocket); closesocket(hSocket);
}
} }
else if (CNode::IsBanned(addr)) else if (CNode::IsBanned(addr))
{ {
@ -651,8 +677,10 @@ void ThreadSocketHandler2(void* parg)
printf("accepted connection %s\n", addr.ToString().c_str()); printf("accepted connection %s\n", addr.ToString().c_str());
CNode* pnode = new CNode(hSocket, addr, true); CNode* pnode = new CNode(hSocket, addr, true);
pnode->AddRef(); pnode->AddRef();
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
vNodes.push_back(pnode); vNodes.push_back(pnode);
}
} }
} }
@ -661,8 +689,8 @@ void ThreadSocketHandler2(void* parg)
// Service each socket // Service each socket
// //
vector<CNode*> vNodesCopy; vector<CNode*> vNodesCopy;
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
vNodesCopy = vNodes; vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy) BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->AddRef(); pnode->AddRef();
@ -679,7 +707,8 @@ void ThreadSocketHandler2(void* parg)
continue; continue;
if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError)) if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
{ {
TRY_CRITICAL_BLOCK(pnode->cs_vRecv) TRY_LOCK(pnode->cs_vRecv, lockRecv);
if (lockRecv)
{ {
CDataStream& vRecv = pnode->vRecv; CDataStream& vRecv = pnode->vRecv;
unsigned int nPos = vRecv.size(); unsigned int nPos = vRecv.size();
@ -728,7 +757,8 @@ void ThreadSocketHandler2(void* parg)
continue; continue;
if (FD_ISSET(pnode->hSocket, &fdsetSend)) if (FD_ISSET(pnode->hSocket, &fdsetSend))
{ {
TRY_CRITICAL_BLOCK(pnode->cs_vSend) TRY_LOCK(pnode->cs_vSend, lockSend);
if (lockSend)
{ {
CDataStream& vSend = pnode->vSend; CDataStream& vSend = pnode->vSend;
if (!vSend.empty()) if (!vSend.empty())
@ -782,8 +812,8 @@ void ThreadSocketHandler2(void* parg)
} }
} }
} }
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodesCopy) BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->Release(); pnode->Release();
} }
@ -1195,8 +1225,10 @@ void ThreadOpenConnections2(void* parg)
// Limit outbound connections // Limit outbound connections
int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125)); int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
vnThreadsRunning[THREAD_OPENCONNECTIONS]--; vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
WAITABLE_CRITICAL_BLOCK(csOutbound) {
WAITABLE_LOCK(csOutbound);
WAIT(condOutbound, fShutdown || nOutbound < nMaxOutbound); WAIT(condOutbound, fShutdown || nOutbound < nMaxOutbound);
}
vnThreadsRunning[THREAD_OPENCONNECTIONS]++; vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown) if (fShutdown)
return; return;
@ -1233,9 +1265,11 @@ void ThreadOpenConnections2(void* parg)
// Only connect to one address per a.b.?.? range. // Only connect to one address per a.b.?.? range.
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect. // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
set<vector<unsigned char> > setConnected; set<vector<unsigned char> > setConnected;
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
setConnected.insert(pnode->addr.GetGroup()); setConnected.insert(pnode->addr.GetGroup());
}
int64 nANow = GetAdjustedTime(); int64 nANow = GetAdjustedTime();
@ -1301,9 +1335,11 @@ void ThreadOpenAddedConnections2(void* parg)
if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0)) if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
{ {
vservAddressesToAdd.push_back(vservNode); vservAddressesToAdd.push_back(vservNode);
CRITICAL_BLOCK(cs_setservAddNodeAddresses) {
LOCK(cs_setservAddNodeAddresses);
BOOST_FOREACH(CService& serv, vservNode) BOOST_FOREACH(CService& serv, vservNode)
setservAddNodeAddresses.insert(serv); setservAddNodeAddresses.insert(serv);
}
} }
} }
loop loop
@ -1311,7 +1347,8 @@ void ThreadOpenAddedConnections2(void* parg)
vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd; vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
// Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
// (keeping in mind that addnode entries can have many IPs if fAllowDNS) // (keeping in mind that addnode entries can have many IPs if fAllowDNS)
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++) for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
BOOST_FOREACH(CService& addrNode, *(it)) BOOST_FOREACH(CService& addrNode, *(it))
@ -1321,6 +1358,7 @@ void ThreadOpenAddedConnections2(void* parg)
it--; it--;
break; break;
} }
}
BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses) BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
{ {
OpenNetworkConnection(CAddress(*(vserv.begin()))); OpenNetworkConnection(CAddress(*(vserv.begin())));
@ -1394,8 +1432,8 @@ void ThreadMessageHandler2(void* parg)
while (!fShutdown) while (!fShutdown)
{ {
vector<CNode*> vNodesCopy; vector<CNode*> vNodesCopy;
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
vNodesCopy = vNodes; vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy) BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->AddRef(); pnode->AddRef();
@ -1408,20 +1446,26 @@ void ThreadMessageHandler2(void* parg)
BOOST_FOREACH(CNode* pnode, vNodesCopy) BOOST_FOREACH(CNode* pnode, vNodesCopy)
{ {
// Receive messages // Receive messages
TRY_CRITICAL_BLOCK(pnode->cs_vRecv) {
ProcessMessages(pnode); TRY_LOCK(pnode->cs_vRecv, lockRecv);
if (lockRecv)
ProcessMessages(pnode);
}
if (fShutdown) if (fShutdown)
return; return;
// Send messages // Send messages
TRY_CRITICAL_BLOCK(pnode->cs_vSend) {
SendMessages(pnode, pnode == pnodeTrickle); TRY_LOCK(pnode->cs_vSend, lockSend);
if (lockSend)
SendMessages(pnode, pnode == pnodeTrickle);
}
if (fShutdown) if (fShutdown)
return; return;
} }
CRITICAL_BLOCK(cs_vNodes)
{ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodesCopy) BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->Release(); pnode->Release();
} }

View file

@ -247,15 +247,19 @@ public:
void AddInventoryKnown(const CInv& inv) void AddInventoryKnown(const CInv& inv)
{ {
CRITICAL_BLOCK(cs_inventory) {
LOCK(cs_inventory);
setInventoryKnown.insert(inv); setInventoryKnown.insert(inv);
}
} }
void PushInventory(const CInv& inv) void PushInventory(const CInv& inv)
{ {
CRITICAL_BLOCK(cs_inventory) {
LOCK(cs_inventory);
if (!setInventoryKnown.count(inv)) if (!setInventoryKnown.count(inv))
vInventoryToSend.push_back(inv); vInventoryToSend.push_back(inv);
}
} }
void AskFor(const CInv& inv) void AskFor(const CInv& inv)
@ -519,8 +523,10 @@ public:
uint256 hashReply; uint256 hashReply;
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
CRITICAL_BLOCK(cs_mapRequests) {
LOCK(cs_mapRequests);
mapRequests[hashReply] = CRequestTracker(fn, param1); mapRequests[hashReply] = CRequestTracker(fn, param1);
}
PushMessage(pszCommand, hashReply); PushMessage(pszCommand, hashReply);
} }
@ -532,8 +538,10 @@ public:
uint256 hashReply; uint256 hashReply;
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
CRITICAL_BLOCK(cs_mapRequests) {
LOCK(cs_mapRequests);
mapRequests[hashReply] = CRequestTracker(fn, param1); mapRequests[hashReply] = CRequestTracker(fn, param1);
}
PushMessage(pszCommand, hashReply, a1); PushMessage(pszCommand, hashReply, a1);
} }
@ -545,8 +553,10 @@ public:
uint256 hashReply; uint256 hashReply;
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
CRITICAL_BLOCK(cs_mapRequests) {
LOCK(cs_mapRequests);
mapRequests[hashReply] = CRequestTracker(fn, param1); mapRequests[hashReply] = CRequestTracker(fn, param1);
}
PushMessage(pszCommand, hashReply, a1, a2); PushMessage(pszCommand, hashReply, a1, a2);
} }
@ -592,9 +602,11 @@ public:
inline void RelayInventory(const CInv& inv) inline void RelayInventory(const CInv& inv)
{ {
// Put on lists to offer to the other nodes // Put on lists to offer to the other nodes
CRITICAL_BLOCK(cs_vNodes) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
pnode->PushInventory(inv); pnode->PushInventory(inv);
}
} }
template<typename T> template<typename T>
@ -609,8 +621,8 @@ void RelayMessage(const CInv& inv, const T& a)
template<> template<>
inline void RelayMessage<>(const CInv& inv, const CDataStream& ss) inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
{ {
CRITICAL_BLOCK(cs_mapRelay)
{ {
LOCK(cs_mapRelay);
// Expire old relay messages // Expire old relay messages
while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
{ {

View file

@ -39,8 +39,8 @@ struct AddressTablePriv
{ {
cachedAddressTable.clear(); cachedAddressTable.clear();
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook) BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook)
{ {
const CBitcoinAddress& address = item.first; const CBitcoinAddress& address = item.first;
@ -169,8 +169,8 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
// Double-check that we're not overwriting a receiving address // Double-check that we're not overwriting a receiving address
if(rec->type == AddressTableEntry::Sending) if(rec->type == AddressTableEntry::Sending)
{ {
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
// Remove old entry // Remove old entry
wallet->DelAddressBookName(rec->address.toStdString()); wallet->DelAddressBookName(rec->address.toStdString());
// Add new entry with new address // Add new entry with new address
@ -254,8 +254,8 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
return QString(); return QString();
} }
// Check for duplicate addresses // Check for duplicate addresses
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
if(wallet->mapAddressBook.count(strAddress)) if(wallet->mapAddressBook.count(strAddress))
{ {
editStatus = DUPLICATE_ADDRESS; editStatus = DUPLICATE_ADDRESS;
@ -286,8 +286,10 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
return QString(); return QString();
} }
// Add entry // Add entry
CRITICAL_BLOCK(wallet->cs_wallet) {
LOCK(wallet->cs_wallet);
wallet->SetAddressBookName(strAddress, strLabel); wallet->SetAddressBookName(strAddress, strLabel);
}
return QString::fromStdString(strAddress); return QString::fromStdString(strAddress);
} }
@ -301,8 +303,8 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
// Also refuse to remove receiving addresses. // Also refuse to remove receiving addresses.
return false; return false;
} }
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
wallet->DelAddressBookName(rec->address.toStdString()); wallet->DelAddressBookName(rec->address.toStdString());
} }
return true; return true;
@ -312,8 +314,8 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
*/ */
QString AddressTableModel::labelForAddress(const QString &address) const QString AddressTableModel::labelForAddress(const QString &address) const
{ {
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
CBitcoinAddress address_parsed(address.toStdString()); CBitcoinAddress address_parsed(address.toStdString());
std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed); std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed);
if (mi != wallet->mapAddressBook.end()) if (mi != wallet->mapAddressBook.end())

View file

@ -34,8 +34,9 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
{ {
QString strHTML; QString strHTML;
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
strHTML.reserve(4000); strHTML.reserve(4000);
strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
@ -243,8 +244,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
strHTML += "<br><b>Inputs:</b>"; strHTML += "<br><b>Inputs:</b>";
strHTML += "<ul>"; strHTML += "<ul>";
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{ {
COutPoint prevout = txin.prevout; COutPoint prevout = txin.prevout;

View file

@ -69,8 +69,8 @@ struct TransactionTablePriv
qDebug() << "refreshWallet"; qDebug() << "refreshWallet";
#endif #endif
cachedWallet.clear(); cachedWallet.clear();
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it) for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
{ {
cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second)); cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second));
@ -95,8 +95,8 @@ struct TransactionTablePriv
QList<uint256> updated_sorted = updated; QList<uint256> updated_sorted = updated;
qSort(updated_sorted); qSort(updated_sorted);
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx) for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx)
{ {
const uint256 &hash = updated_sorted.at(update_idx); const uint256 &hash = updated_sorted.at(update_idx);
@ -171,8 +171,8 @@ struct TransactionTablePriv
// simply re-use the cached status. // simply re-use the cached status.
if(rec->statusUpdateNeeded()) if(rec->statusUpdateNeeded())
{ {
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash); std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != wallet->mapWallet.end()) if(mi != wallet->mapWallet.end())
@ -191,8 +191,8 @@ struct TransactionTablePriv
QString describe(TransactionRecord *rec) QString describe(TransactionRecord *rec)
{ {
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash); std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != wallet->mapWallet.end()) if(mi != wallet->mapWallet.end())
{ {
@ -229,9 +229,9 @@ void TransactionTableModel::update()
QList<uint256> updated; QList<uint256> updated;
// Check if there are changes to wallet map // Check if there are changes to wallet map
TRY_CRITICAL_BLOCK(wallet->cs_wallet)
{ {
if(!wallet->vWalletUpdated.empty()) TRY_LOCK(wallet->cs_wallet, lockWallet);
if (lockWallet && !wallet->vWalletUpdated.empty())
{ {
BOOST_FOREACH(uint256 hash, wallet->vWalletUpdated) BOOST_FOREACH(uint256 hash, wallet->vWalletUpdated)
{ {

View file

@ -32,8 +32,8 @@ qint64 WalletModel::getUnconfirmedBalance() const
int WalletModel::getNumTransactions() const int WalletModel::getNumTransactions() const
{ {
int numTransactions = 0; int numTransactions = 0;
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
numTransactions = wallet->mapWallet.size(); numTransactions = wallet->mapWallet.size();
} }
return numTransactions; return numTransactions;
@ -115,9 +115,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee);
} }
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK2(cs_main, wallet->cs_wallet);
// Sendmany // Sendmany
std::vector<std::pair<CScript, int64> > vecSend; std::vector<std::pair<CScript, int64> > vecSend;
foreach(const SendCoinsRecipient &rcp, recipients) foreach(const SendCoinsRecipient &rcp, recipients)
@ -155,8 +155,8 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
foreach(const SendCoinsRecipient &rcp, recipients) foreach(const SendCoinsRecipient &rcp, recipients)
{ {
std::string strAddress = rcp.address.toStdString(); std::string strAddress = rcp.address.toStdString();
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
if (!wallet->mapAddressBook.count(strAddress)) if (!wallet->mapAddressBook.count(strAddress))
wallet->SetAddressBookName(strAddress, rcp.label.toStdString()); wallet->SetAddressBookName(strAddress, rcp.label.toStdString());
} }
@ -227,8 +227,8 @@ bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass) bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
{ {
bool retval; bool retval;
CRITICAL_BLOCK(wallet->cs_wallet)
{ {
LOCK(wallet->cs_wallet);
wallet->Lock(); // Make sure wallet is locked before attempting pass change wallet->Lock(); // Make sure wallet is locked before attempting pass change
retval = wallet->ChangeWalletPassphrase(oldPass, newPass); retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
} }

View file

@ -60,9 +60,9 @@ Value importprivkey(const Array& params, bool fHelp)
key.SetSecret(secret, fCompressed); key.SetSecret(secret, fCompressed);
CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey()); CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey());
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{ {
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->MarkDirty(); pwalletMain->MarkDirty();
pwalletMain->SetAddressBookName(vchAddress, strLabel); pwalletMain->SetAddressBookName(vchAddress, strLabel);

View file

@ -15,14 +15,15 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
CCriticalSection cs; CCriticalSection cs;
do { do {
CRITICAL_BLOCK(cs) LOCK(cs);
break; break;
BOOST_ERROR("break was swallowed!"); BOOST_ERROR("break was swallowed!");
} while(0); } while(0);
do { do {
TRY_CRITICAL_BLOCK(cs) TRY_LOCK(cs, lockTest);
if (lockTest)
break; break;
BOOST_ERROR("break was swallowed!"); BOOST_ERROR("break was swallowed!");

View file

@ -196,8 +196,8 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
static CCriticalSection cs_OutputDebugStringF; static CCriticalSection cs_OutputDebugStringF;
// accumulate a line at a time // accumulate a line at a time
CRITICAL_BLOCK(cs_OutputDebugStringF)
{ {
LOCK(cs_OutputDebugStringF);
static char pszBuffer[50000]; static char pszBuffer[50000];
static char* pend; static char* pend;
if (pend == NULL) if (pend == NULL)
@ -1120,25 +1120,25 @@ private:
int sourceLine; int sourceLine;
}; };
typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack; typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
static boost::interprocess::interprocess_mutex dd_mutex; static boost::interprocess::interprocess_mutex dd_mutex;
static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders; static std::map<std::pair<void*, void*>, LockStack> lockorders;
static boost::thread_specific_ptr<LockStack> lockstack; static boost::thread_specific_ptr<LockStack> lockstack;
static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2) static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{ {
printf("POTENTIAL DEADLOCK DETECTED\n"); printf("POTENTIAL DEADLOCK DETECTED\n");
printf("Previous lock order was:\n"); printf("Previous lock order was:\n");
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
{ {
if (i.first == mismatch.first) printf(" (1)"); if (i.first == mismatch.first) printf(" (1)");
if (i.first == mismatch.second) printf(" (2)"); if (i.first == mismatch.second) printf(" (2)");
printf(" %s\n", i.second.ToString().c_str()); printf(" %s\n", i.second.ToString().c_str());
} }
printf("Current lock order is:\n"); printf("Current lock order is:\n");
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
{ {
if (i.first == mismatch.first) printf(" (1)"); if (i.first == mismatch.first) printf(" (1)");
if (i.first == mismatch.second) printf(" (2)"); if (i.first == mismatch.second) printf(" (2)");
@ -1146,7 +1146,7 @@ static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCrit
} }
} }
static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
{ {
bool fOrderOK = true; bool fOrderOK = true;
if (lockstack.get() == NULL) if (lockstack.get() == NULL)
@ -1157,16 +1157,16 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
(*lockstack).push_back(std::make_pair(c, locklocation)); (*lockstack).push_back(std::make_pair(c, locklocation));
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack)) if (!fTry) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack))
{ {
if (i.first == c) break; if (i.first == c) break;
std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c); std::pair<void*, void*> p1 = std::make_pair(i.first, c);
if (lockorders.count(p1)) if (lockorders.count(p1))
continue; continue;
lockorders[p1] = (*lockstack); lockorders[p1] = (*lockstack);
std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first); std::pair<void*, void*> p2 = std::make_pair(c, i.first);
if (lockorders.count(p2)) if (lockorders.count(p2))
{ {
potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
@ -1188,9 +1188,9 @@ static void pop_lock()
dd_mutex.unlock(); dd_mutex.unlock();
} }
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs) void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{ {
push_lock(cs, CLockLocation(pszName, pszFile, nLine)); push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
} }
void LeaveCritical() void LeaveCritical()

View file

@ -190,10 +190,10 @@ typedef boost::interprocess::interprocess_recursive_mutex CCriticalSection;
typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection; typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection;
#ifdef DEBUG_LOCKORDER #ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs); void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical(); void LeaveCritical();
#else #else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs) {} void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {} void static inline LeaveCritical() {}
#endif #endif
@ -234,7 +234,7 @@ public:
{ {
if (!lock.owns()) if (!lock.owns())
{ {
EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex())); EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
lock.try_lock(); lock.try_lock();
if (!lock.owns()) if (!lock.owns())
LeaveCritical(); LeaveCritical();
@ -282,13 +282,10 @@ typedef boost::interprocess::interprocess_condition CConditionVariable;
#define NOTIFY_ALL(name) \ #define NOTIFY_ALL(name) \
do { (name).notify_all(); } while(0) do { (name).notify_all(); } while(0)
#define CRITICAL_BLOCK(cs) \ #define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \ #define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
for (CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false) #define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
#define WAITABLE_LOCK(cs) CWaitableCriticalBlock waitablecriticalblock(cs, #cs, __FILE__, __LINE__)
#define WAITABLE_CRITICAL_BLOCK(cs) \
for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by WAITABLE_CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \
for (CWaitableCriticalBlock waitablecriticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false)
#define ENTER_CRITICAL_SECTION(cs) \ #define ENTER_CRITICAL_SECTION(cs) \
{ \ { \
@ -302,10 +299,6 @@ typedef boost::interprocess::interprocess_condition CConditionVariable;
LeaveCritical(); \ LeaveCritical(); \
} }
#define TRY_CRITICAL_BLOCK(cs) \
for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \
for (CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__, true); fcriticalblockonce && (fcriticalblockonce = criticalblock); fcriticalblockonce=false)
// This is exactly like std::string, but with a custom allocator. // This is exactly like std::string, but with a custom allocator.
// (secure_allocator<> is defined in serialize.h) // (secure_allocator<> is defined in serialize.h)

View file

@ -49,8 +49,8 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
return false; return false;
if (!fFileBacked) if (!fFileBacked)
return true; return true;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
if (pwalletdbEncryption) if (pwalletdbEncryption)
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret); return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
else else
@ -76,7 +76,8 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
CCrypter crypter; CCrypter crypter;
CKeyingMaterial vMasterKey; CKeyingMaterial vMasterKey;
CRITICAL_BLOCK(cs_wallet) {
LOCK(cs_wallet);
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
{ {
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
@ -86,6 +87,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
if (CCryptoKeyStore::Unlock(vMasterKey)) if (CCryptoKeyStore::Unlock(vMasterKey))
return true; return true;
} }
}
return false; return false;
} }
@ -93,8 +95,8 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
{ {
bool fWasLocked = IsLocked(); bool fWasLocked = IsLocked();
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
Lock(); Lock();
CCrypter crypter; CCrypter crypter;
@ -228,8 +230,8 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey)) if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
return false; return false;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
if (fFileBacked) if (fFileBacked)
{ {
@ -275,8 +277,8 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
// Anytime a signature is successfully verified, it's proof the outpoint is spent. // Anytime a signature is successfully verified, it's proof the outpoint is spent.
// Update the wallet spent flag if it doesn't know due to wallet.dat being // Update the wallet spent flag if it doesn't know due to wallet.dat being
// restored from backup or the user making copies of wallet.dat. // restored from backup or the user making copies of wallet.dat.
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
BOOST_FOREACH(const CTxIn& txin, tx.vin) BOOST_FOREACH(const CTxIn& txin, tx.vin)
{ {
map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash); map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
@ -297,8 +299,8 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
void CWallet::MarkDirty() void CWallet::MarkDirty()
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
item.second.MarkDirty(); item.second.MarkDirty();
} }
@ -307,8 +309,8 @@ void CWallet::MarkDirty()
bool CWallet::AddToWallet(const CWalletTx& wtxIn) bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{ {
uint256 hash = wtxIn.GetHash(); uint256 hash = wtxIn.GetHash();
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
// Inserts only if not already there, returns tx inserted or tx found // Inserts only if not already there, returns tx inserted or tx found
pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
CWalletTx& wtx = (*ret.first).second; CWalletTx& wtx = (*ret.first).second;
@ -382,8 +384,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock) bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
{ {
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
bool fExisted = mapWallet.count(hash); bool fExisted = mapWallet.count(hash);
if (fExisted && !fUpdate) return false; if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx) || IsFromMe(tx)) if (fExisted || IsMine(tx) || IsFromMe(tx))
@ -404,8 +406,8 @@ bool CWallet::EraseFromWallet(uint256 hash)
{ {
if (!fFileBacked) if (!fFileBacked)
return false; return false;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
if (mapWallet.erase(hash)) if (mapWallet.erase(hash))
CWalletDB(strWalletFile).EraseTx(hash); CWalletDB(strWalletFile).EraseTx(hash);
} }
@ -415,8 +417,8 @@ bool CWallet::EraseFromWallet(uint256 hash)
bool CWallet::IsMine(const CTxIn &txin) const bool CWallet::IsMine(const CTxIn &txin) const
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash); map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end()) if (mi != mapWallet.end())
{ {
@ -431,8 +433,8 @@ bool CWallet::IsMine(const CTxIn &txin) const
int64 CWallet::GetDebit(const CTxIn &txin) const int64 CWallet::GetDebit(const CTxIn &txin) const
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash); map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end()) if (mi != mapWallet.end())
{ {
@ -457,9 +459,11 @@ bool CWallet::IsChange(const CTxOut& txout) const
// 'the change' will need to be implemented (maybe extend CWalletTx to remember // 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change). // which output, if any, was change).
if (ExtractAddress(txout.scriptPubKey, address) && HaveKey(address)) if (ExtractAddress(txout.scriptPubKey, address) && HaveKey(address))
CRITICAL_BLOCK(cs_wallet) {
if (!mapAddressBook.count(address)) LOCK(cs_wallet);
return true; if (!mapAddressBook.count(address))
return true;
}
return false; return false;
} }
@ -472,8 +476,8 @@ int CWalletTx::GetRequestCount() const
{ {
// Returns -1 if it wasn't being tracked // Returns -1 if it wasn't being tracked
int nRequests = -1; int nRequests = -1;
CRITICAL_BLOCK(pwallet->cs_wallet)
{ {
LOCK(pwallet->cs_wallet);
if (IsCoinBase()) if (IsCoinBase())
{ {
// Generated block // Generated block
@ -577,8 +581,8 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
nSent += s.second; nSent += s.second;
nFee = allFee; nFee = allFee;
} }
CRITICAL_BLOCK(pwallet->cs_wallet)
{ {
LOCK(pwallet->cs_wallet);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived) BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
{ {
if (pwallet->mapAddressBook.count(r.first)) if (pwallet->mapAddressBook.count(r.first))
@ -607,8 +611,8 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
vWorkQueue.push_back(txin.prevout.hash); vWorkQueue.push_back(txin.prevout.hash);
// This critsect is OK because txdb is already open // This critsect is OK because txdb is already open
CRITICAL_BLOCK(pwallet->cs_wallet)
{ {
LOCK(pwallet->cs_wallet);
map<uint256, const CMerkleTx*> mapWalletPrev; map<uint256, const CMerkleTx*> mapWalletPrev;
set<uint256> setAlreadyDone; set<uint256> setAlreadyDone;
for (int i = 0; i < vWorkQueue.size(); i++) for (int i = 0; i < vWorkQueue.size(); i++)
@ -666,8 +670,8 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
int ret = 0; int ret = 0;
CBlockIndex* pindex = pindexStart; CBlockIndex* pindex = pindexStart;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
while (pindex) while (pindex)
{ {
CBlock block; CBlock block;
@ -696,8 +700,9 @@ void CWallet::ReacceptWalletTransactions()
{ {
CTxDB txdb("r"); CTxDB txdb("r");
bool fRepeat = true; bool fRepeat = true;
while (fRepeat) CRITICAL_BLOCK(cs_wallet) while (fRepeat)
{ {
LOCK(cs_wallet);
fRepeat = false; fRepeat = false;
vector<CDiskTxPos> vMissingTx; vector<CDiskTxPos> vMissingTx;
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
@ -799,8 +804,8 @@ void CWallet::ResendWalletTransactions()
// Rebroadcast any of our txes that aren't in a block yet // Rebroadcast any of our txes that aren't in a block yet
printf("ResendWalletTransactions()\n"); printf("ResendWalletTransactions()\n");
CTxDB txdb("r"); CTxDB txdb("r");
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
// Sort them in chronological order // Sort them in chronological order
multimap<unsigned int, CWalletTx*> mapSorted; multimap<unsigned int, CWalletTx*> mapSorted;
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
@ -833,8 +838,8 @@ void CWallet::ResendWalletTransactions()
int64 CWallet::GetBalance() const int64 CWallet::GetBalance() const
{ {
int64 nTotal = 0; int64 nTotal = 0;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{ {
const CWalletTx* pcoin = &(*it).second; const CWalletTx* pcoin = &(*it).second;
@ -850,8 +855,8 @@ int64 CWallet::GetBalance() const
int64 CWallet::GetUnconfirmedBalance() const int64 CWallet::GetUnconfirmedBalance() const
{ {
int64 nTotal = 0; int64 nTotal = 0;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{ {
const CWalletTx* pcoin = &(*it).second; const CWalletTx* pcoin = &(*it).second;
@ -875,8 +880,8 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe
vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue; vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
int64 nTotalLower = 0; int64 nTotalLower = 0;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
vector<const CWalletTx*> vCoins; vector<const CWalletTx*> vCoins;
vCoins.reserve(mapWallet.size()); vCoins.reserve(mapWallet.size());
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@ -1032,9 +1037,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
wtxNew.BindWallet(this); wtxNew.BindWallet(this);
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK2(cs_main, cs_wallet);
// txdb must be opened before the mapWallet lock // txdb must be opened before the mapWallet lock
CTxDB txdb("r"); CTxDB txdb("r");
{ {
@ -1146,9 +1150,8 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w
// Call after CreateTransaction unless you want to abort // Call after CreateTransaction unless you want to abort
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{ {
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK2(cs_main, cs_wallet);
printf("CommitTransaction:\n%s", wtxNew.ToString().c_str()); printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
{ {
// This is only to keep the database open to defeat the auto-flush for the // This is only to keep the database open to defeat the auto-flush for the
@ -1297,8 +1300,8 @@ bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
void CWallet::PrintWallet(const CBlock& block) void CWallet::PrintWallet(const CBlock& block)
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
if (mapWallet.count(block.vtx[0].GetHash())) if (mapWallet.count(block.vtx[0].GetHash()))
{ {
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
@ -1310,8 +1313,8 @@ void CWallet::PrintWallet(const CBlock& block)
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx) bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx); map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
if (mi != mapWallet.end()) if (mi != mapWallet.end())
{ {
@ -1347,8 +1350,8 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
// //
bool CWallet::NewKeyPool() bool CWallet::NewKeyPool()
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
CWalletDB walletdb(strWalletFile); CWalletDB walletdb(strWalletFile);
BOOST_FOREACH(int64 nIndex, setKeyPool) BOOST_FOREACH(int64 nIndex, setKeyPool)
walletdb.ErasePool(nIndex); walletdb.ErasePool(nIndex);
@ -1371,8 +1374,9 @@ bool CWallet::NewKeyPool()
bool CWallet::TopUpKeyPool() bool CWallet::TopUpKeyPool()
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
if (IsLocked()) if (IsLocked())
return false; return false;
@ -1398,8 +1402,9 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{ {
nIndex = -1; nIndex = -1;
keypool.vchPubKey.clear(); keypool.vchPubKey.clear();
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
if (!IsLocked()) if (!IsLocked())
TopUpKeyPool(); TopUpKeyPool();
@ -1422,9 +1427,8 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
int64 CWallet::AddReserveKey(const CKeyPool& keypool) int64 CWallet::AddReserveKey(const CKeyPool& keypool)
{ {
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK2(cs_main, cs_wallet);
CWalletDB walletdb(strWalletFile); CWalletDB walletdb(strWalletFile);
int64 nIndex = 1 + *(--setKeyPool.end()); int64 nIndex = 1 + *(--setKeyPool.end());
@ -1450,8 +1454,10 @@ void CWallet::KeepKey(int64 nIndex)
void CWallet::ReturnKey(int64 nIndex) void CWallet::ReturnKey(int64 nIndex)
{ {
// Return to key pool // Return to key pool
CRITICAL_BLOCK(cs_wallet) {
LOCK(cs_wallet);
setKeyPool.insert(nIndex); setKeyPool.insert(nIndex);
}
printf("keypool return %"PRI64d"\n", nIndex); printf("keypool return %"PRI64d"\n", nIndex);
} }
@ -1459,8 +1465,8 @@ bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
{ {
int64 nIndex = 0; int64 nIndex = 0;
CKeyPool keypool; CKeyPool keypool;
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
ReserveKeyFromKeyPool(nIndex, keypool); ReserveKeyFromKeyPool(nIndex, keypool);
if (nIndex == -1) if (nIndex == -1)
{ {
@ -1530,8 +1536,7 @@ void CWallet::GetAllReserveAddresses(set<CBitcoinAddress>& setAddress)
CWalletDB walletdb(strWalletFile); CWalletDB walletdb(strWalletFile);
CRITICAL_BLOCK(cs_main) LOCK2(cs_main, cs_wallet);
CRITICAL_BLOCK(cs_wallet)
BOOST_FOREACH(const int64& id, setKeyPool) BOOST_FOREACH(const int64& id, setKeyPool)
{ {
CKeyPool keypool; CKeyPool keypool;

View file

@ -211,16 +211,18 @@ public:
void UpdatedTransaction(const uint256 &hashTx) void UpdatedTransaction(const uint256 &hashTx)
{ {
CRITICAL_BLOCK(cs_wallet) {
LOCK(cs_wallet);
vWalletUpdated.push_back(hashTx); vWalletUpdated.push_back(hashTx);
}
} }
void PrintWallet(const CBlock& block); void PrintWallet(const CBlock& block);
void Inventory(const uint256 &hash) void Inventory(const uint256 &hash)
{ {
CRITICAL_BLOCK(cs_wallet)
{ {
LOCK(cs_wallet);
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash); std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
if (mi != mapRequestCount.end()) if (mi != mapRequestCount.end())
(*mi).second++; (*mi).second++;