Solve chainActive-related locking issues

- In wallet and GUI code LOCK cs_main as well as cs_wallet when
  necessary
- In main.cpp SendMessages move the TRY_LOCK(cs_main) up, to encompass the call
  to IsInitialBlockDownload.
- Make ActivateBestChain, AddToBlockIndex, IsInitialBlockDownload,
  InitBlockIndex acquire the cs_main lock

Fixes #3997
This commit is contained in:
Wladimir J. van der Laan
2014-04-15 17:38:25 +02:00
parent e07c943ce8
commit 55a1db4fa2
7 changed files with 269 additions and 272 deletions

View File

@@ -1310,7 +1310,7 @@ int GetNumBlocksOfPeers()
bool IsInitialBlockDownload()
{
AssertLockHeld(cs_main);
LOCK(cs_main);
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
return true;
static int64_t nLastUpdate;
@@ -2087,7 +2087,7 @@ void static FindMostWorkChain() {
// Try to activate to the most-work chain (thereby connecting it).
bool ActivateBestChain(CValidationState &state) {
AssertLockHeld(cs_main);
LOCK(cs_main);
CBlockIndex *pindexOldTip = chainActive.Tip();
bool fComplete = false;
while (!fComplete) {
@@ -2136,7 +2136,6 @@ bool ActivateBestChain(CValidationState &state) {
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{
AssertLockHeld(cs_main);
// Check for duplicate
uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash))
@@ -2173,6 +2172,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
if (!ActivateBestChain(state))
return false;
LOCK(cs_main);
if (pindexNew == chainActive.Tip())
{
// Clear fork warning if its no longer applicable
@@ -2962,6 +2962,7 @@ bool LoadBlockIndex()
bool InitBlockIndex() {
LOCK(cs_main);
// Check whether we're already initialized
if (chainActive.Genesis() != NULL)
return true;
@@ -4201,6 +4202,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
}
}
TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
if (!lockMain)
return true;
// Address refresh broadcast
static int64_t nLastRebroadcast;
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
@@ -4251,10 +4256,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pto->PushMessage("addr", vAddr);
}
TRY_LOCK(cs_main, lockMain);
if (!lockMain)
return true;
CNodeState &state = *State(pto->GetId());
if (state.fShouldBan) {
if (pto->addr.IsLocal())