Skip to content
This repository has been archived by the owner on Feb 1, 2021. It is now read-only.

resolve reindexing deadlock/crash #188

Merged
merged 5 commits into from
May 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/chain/blockindex.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,12 @@ class CBlockIndex

const CBlockIndex *pindex = this;
for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
*(--pbegin) = pindex->GetBlockTime();
{
if (pindex)
{
*(--pbegin) = pindex->GetBlockTime();
}
}

std::sort(pbegin, pend);
return pbegin[(pend - pbegin) / 2];
Expand Down
5 changes: 3 additions & 2 deletions src/chain/chainman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ bool CChainManager::LoadBlockIndexDB()

bool CChainManager::LoadExternalBlockFile(const CNetworkTemplate &chainparams, FILE *fileIn, CDiskBlockPos *dbp)
{
WRITELOCK(cs_mapBlockIndex);
// std::map of disk positions for blocks with unknown parent (only used for reindex)
static std::multimap<uint256, CDiskBlockPos> mapBlocksUnknownParent;
int64_t nStart = GetTimeMillis();
Expand All @@ -348,7 +347,7 @@ bool CChainManager::LoadExternalBlockFile(const CNetworkTemplate &chainparams, F
{
if (shutdown_threads.load())
{
break;
return nLoaded;
}

blkdat.SetPos(nRewind);
Expand Down Expand Up @@ -453,7 +452,9 @@ bool CChainManager::LoadExternalBlockFile(const CNetworkTemplate &chainparams, F
AbortNode(std::string("System error: ") + e.what());
}
if (nLoaded > 0)
{
LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
}
return nLoaded > 0;
}

Expand Down
5 changes: 4 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,10 +695,14 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
{
CDiskBlockPos pos(nFile, 0);
if (!fs::exists(GetBlockPosFilename(pos, "blk")))
{
break; // No block files left to reindex
}
FILE *file = OpenBlockFile(pos, true);
if (!file)
{
break; // This error is logged in OpenBlockFile
}
LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
pnetMan->getChainActive()->LoadExternalBlockFile(chainparams, file, &pos);
nFile++;
Expand Down Expand Up @@ -1440,7 +1444,6 @@ bool AppInit2(thread_group &threadGroup)
LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (1.0 / 1024 / 1024));

LOCK(cs_main);
bool fLoaded = false;
while (!fLoaded)
{
Expand Down
35 changes: 15 additions & 20 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ bool AcceptToMemoryPool(CTxMemPool &pool,
bool fRejectAbsurdFee)
{
std::vector<COutPoint> vCoinsToUncache;
LOCK(cs_main);
bool res = AcceptToMemoryPoolWorker(
pool, state, tx, fLimitFree, pfMissingInputs, fOverrideMempoolLimit, fRejectAbsurdFee, vCoinsToUncache);
if (pfMissingInputs && !res && !*pfMissingInputs)
Expand Down Expand Up @@ -1266,8 +1267,7 @@ void PruneBlockIndexCandidates()

bool InvalidateBlock(CValidationState &state, const Consensus::Params &consensusParams, CBlockIndex *pindex)
{
AssertLockHeld(cs_main);

WRITELOCK(pnetMan->getChainActive()->cs_mapBlockIndex);
// Mark the block itself as invalid.
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
Expand All @@ -1292,20 +1292,15 @@ bool InvalidateBlock(CValidationState &state, const Consensus::Params &consensus
LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000,
gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);

// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
// add it again.
BlockMap::iterator it = pnetMan->getChainActive()->mapBlockIndex.begin();
while (it != pnetMan->getChainActive()->mapBlockIndex.end())
{
READLOCK(pnetMan->getChainActive()->cs_mapBlockIndex);
BlockMap::iterator it = pnetMan->getChainActive()->mapBlockIndex.begin();
while (it != pnetMan->getChainActive()->mapBlockIndex.end())
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx &&
!setBlockIndexCandidates.value_comp()(it->second, pnetMan->getChainActive()->chainActive.Tip()))
{
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx &&
!setBlockIndexCandidates.value_comp()(it->second, pnetMan->getChainActive()->chainActive.Tip()))
{
setBlockIndexCandidates.insert(it->second);
}
it++;
setBlockIndexCandidates.insert(it->second);
}
it++;
}

InvalidChainFound(pindex);
Expand All @@ -1316,11 +1311,8 @@ bool InvalidateBlock(CValidationState &state, const Consensus::Params &consensus

bool ReconsiderBlock(CValidationState &state, CBlockIndex *pindex)
{
AssertLockHeld(cs_main);

int nHeight = pindex->nHeight;

READLOCK(pnetMan->getChainActive()->cs_mapBlockIndex);
WRITELOCK(pnetMan->getChainActive()->cs_mapBlockIndex);
// Remove the invalidity flag from this block
if (!pindex->IsValid())
{
Expand All @@ -1337,7 +1329,6 @@ bool ReconsiderBlock(CValidationState &state, CBlockIndex *pindex)
pindexBestInvalid = NULL;
}
}

// Remove the invalidity flag from all descendants.
BlockMap::iterator it = pnetMan->getChainActive()->mapBlockIndex.begin();
while (it != pnetMan->getChainActive()->mapBlockIndex.end())
Expand Down Expand Up @@ -1655,8 +1646,12 @@ bool ContextualCheckBlock(const CBlock &block, CValidationState &state, CBlockIn
int nLockTimeFlags = 0;
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;

int64_t nLockTimeCutoff =
(nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) ? pindexPrev->GetMedianTimePast() : block.GetBlockTime();
int64_t nLockTimeCutoff;
if (pindexPrev == nullptr)
nLockTimeCutoff = block.GetBlockTime();
else
nLockTimeCutoff =
(nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) ? pindexPrev->GetMedianTimePast() : block.GetBlockTime();

// Check that all transactions are finalized
for (auto const &tx : block.vtx)
Expand Down
1 change: 0 additions & 1 deletion src/net/messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ std::unique_ptr<CRollingBloomFilter> recentRejects;
std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> > mapBlocksInFlight;
uint256 hashRecentRejectsChainTip;
std::map<uint256, std::pair<NodeId, bool> > mapBlockSource;
/** Relay map, protected by cs_main. */
CCriticalSection cs_mapRelay;
std::map<uint256, CTransaction> mapRelay;
std::deque<std::pair<int64_t, std::map<uint256, CTransaction>::iterator> > vRelayExpiration;
Expand Down
1 change: 0 additions & 1 deletion src/rpc/rpcblockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,6 @@ static std::set<CBlockIndex *, CompareBlocksByHeight> GetChainTips()
std::set<CBlockIndex *> setOrphans;
std::set<CBlockIndex *> setPrevs;

AssertLockHeld(cs_main); // for chainActive
READLOCK(pnetMan->getChainActive()->cs_mapBlockIndex);
for (const std::pair<const uint256, CBlockIndex *> &item : pnetMan->getChainActive()->mapBlockIndex)
{
Expand Down