Merge #8392: Fix several node initialization issues

9d4eb9a Do diskspace check before import thread is started (Pieter Wuille)
aa59f2e Add extra message to avoid a long 'Loading banlist' (Pieter Wuille)
0fd2a33 Use a signal to continue init after genesis activation (Pieter Wuille)
This commit is contained in:
Wladimir J. van der Laan 2016-08-04 12:21:59 +02:00
commit f97d335942
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
4 changed files with 40 additions and 15 deletions

View File

@ -511,6 +511,21 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex
boost::thread t(runCommand, strCmd); // thread runs free boost::thread t(runCommand, strCmd); // thread runs free
} }
static bool fHaveGenesis = false;
static boost::mutex cs_GenesisWait;
static CConditionVariable condvar_GenesisWait;
static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
{
if (pBlockIndex != NULL) {
{
boost::unique_lock<boost::mutex> lock_GenesisWait(cs_GenesisWait);
fHaveGenesis = true;
}
condvar_GenesisWait.notify_all();
}
}
struct CImportingNow struct CImportingNow
{ {
CImportingNow() { CImportingNow() {
@ -1322,7 +1337,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
break; break;
} }
if (!fReindex) { if (!fReindex && chainActive.Tip() != NULL) {
uiInterface.InitMessage(_("Rewinding blocks...")); uiInterface.InitMessage(_("Rewinding blocks..."));
if (!RewindBlockIndex(chainparams)) { if (!RewindBlockIndex(chainparams)) {
strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain"); strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
@ -1439,6 +1454,17 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// ********************************************************* Step 10: import blocks // ********************************************************* Step 10: import blocks
if (!CheckDiskSpace())
return false;
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
// No locking, as this happens before any background thread is started.
if (chainActive.Tip() == NULL) {
uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait);
} else {
fHaveGenesis = true;
}
if (mapArgs.count("-blocknotify")) if (mapArgs.count("-blocknotify"))
uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); uiInterface.NotifyBlockTip.connect(BlockNotifyCallback);
@ -1448,26 +1474,20 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"]) BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"])
vImportFiles.push_back(strFile); vImportFiles.push_back(strFile);
} }
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
// Wait for genesis block to be processed // Wait for genesis block to be processed
bool fHaveGenesis = false; {
while (!fHaveGenesis && !fRequestShutdown) { boost::unique_lock<boost::mutex> lock(cs_GenesisWait);
{ while (!fHaveGenesis) {
LOCK(cs_main); condvar_GenesisWait.wait(lock);
fHaveGenesis = (chainActive.Tip() != NULL);
}
if (!fHaveGenesis) {
MilliSleep(10);
} }
uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait);
} }
// ********************************************************* Step 11: start node // ********************************************************* Step 11: start node
if (!CheckDiskSpace())
return false;
if (!strErrors.str().empty()) if (!strErrors.str().empty())
return InitError(strErrors.str()); return InitError(strErrors.str());

View File

@ -4313,8 +4313,6 @@ bool InitBlockIndex(const CChainParams& chainparams)
CBlockIndex *pindex = AddToBlockIndex(block); CBlockIndex *pindex = AddToBlockIndex(block);
if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("LoadBlockIndex(): genesis block not accepted"); return error("LoadBlockIndex(): genesis block not accepted");
if (!ActivateBestChain(state, chainparams, &block))
return error("LoadBlockIndex(): genesis block cannot be activated");
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data // Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
return FlushStateToDisk(state, FLUSH_STATE_ALWAYS); return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {

View File

@ -2050,6 +2050,8 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
DumpBanlist(); DumpBanlist();
} }
uiInterface.InitMessage(_("Starting network threads..."));
fAddressesInitialized = true; fAddressesInitialized = true;
if (semOutbound == NULL) { if (semOutbound == NULL) {

View File

@ -60,6 +60,11 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinsdbview);
InitBlockIndex(chainparams); InitBlockIndex(chainparams);
{
CValidationState state;
bool ok = ActivateBestChain(state, chainparams);
BOOST_CHECK(ok);
}
nScriptCheckThreads = 3; nScriptCheckThreads = 3;
for (int i=0; i < nScriptCheckThreads-1; i++) for (int i=0; i < nScriptCheckThreads-1; i++)
threadGroup.create_thread(&ThreadScriptCheck); threadGroup.create_thread(&ThreadScriptCheck);