Changeset View
Changeset View
Standalone View
Standalone View
src/init.cpp
Show All 11 Lines | |||||
#include <addrman.h> | #include <addrman.h> | ||||
#include <amount.h> | #include <amount.h> | ||||
#include <avalanche.h> | #include <avalanche.h> | ||||
#include <banman.h> | #include <banman.h> | ||||
#include <blockfilter.h> | #include <blockfilter.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <chainparams.h> | #include <chainparams.h> | ||||
#include <checkpoints.h> | #include <checkpoints.h> | ||||
#include <coins.h> | |||||
#include <compat/sanity.h> | #include <compat/sanity.h> | ||||
#include <config.h> | #include <config.h> | ||||
#include <consensus/validation.h> | #include <consensus/validation.h> | ||||
#include <flatfile.h> | #include <flatfile.h> | ||||
#include <fs.h> | #include <fs.h> | ||||
#include <httprpc.h> | #include <httprpc.h> | ||||
#include <httpserver.h> | #include <httpserver.h> | ||||
#include <index/blockfilterindex.h> | #include <index/blockfilterindex.h> | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | |||||
// causes AppInit() to continue (it .joins the shutdown thread). Shutdown() is | // causes AppInit() to continue (it .joins the shutdown thread). Shutdown() is | ||||
// then called to clean up database connections, and stop other threads that | // then called to clean up database connections, and stop other threads that | ||||
// should only be stopped after the main network-processing threads have exited. | // should only be stopped after the main network-processing threads have exited. | ||||
// | // | ||||
// Shutdown for Qt is very similar, only it uses a QTimer to detect | // Shutdown for Qt is very similar, only it uses a QTimer to detect | ||||
// ShutdownRequested() getting set, and then does the normal Qt shutdown thing. | // ShutdownRequested() getting set, and then does the normal Qt shutdown thing. | ||||
// | // | ||||
/** | |||||
* This is a minimally invasive approach to shutdown on LevelDB read errors from | |||||
* the chainstate, while keeping user interface out of the common library, which | |||||
* is shared between bitcoind, and bitcoin-qt and non-server tools. | |||||
*/ | |||||
class CCoinsViewErrorCatcher final : public CCoinsViewBacked { | |||||
public: | |||||
explicit CCoinsViewErrorCatcher(CCoinsView *view) | |||||
: CCoinsViewBacked(view) {} | |||||
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override { | |||||
try { | |||||
return CCoinsViewBacked::GetCoin(outpoint, coin); | |||||
} catch (const std::runtime_error &e) { | |||||
uiInterface.ThreadSafeMessageBox( | |||||
_("Error reading from database, shutting down.").translated, "", | |||||
CClientUIInterface::MSG_ERROR); | |||||
LogPrintf("Error reading from database: %s\n", e.what()); | |||||
// Starting the shutdown sequence and returning false to the caller | |||||
// would be interpreted as 'entry not found' (as opposed to unable | |||||
// to read data), and could lead to invalid interpretation. Just | |||||
// exit immediately, as we can't continue anyway, and all writes | |||||
// should be atomic. | |||||
abort(); | |||||
} | |||||
} | |||||
// Writes do not need similar protection, as failure to write is handled by | |||||
// the caller. | |||||
}; | |||||
static std::unique_ptr<CCoinsViewErrorCatcher> pcoinscatcher; | static std::unique_ptr<CCoinsViewErrorCatcher> pcoinscatcher; | ||||
static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; | static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; | ||||
static boost::thread_group threadGroup; | static boost::thread_group threadGroup; | ||||
void Interrupt(NodeContext &node) { | void Interrupt(NodeContext &node) { | ||||
InterruptHTTPServer(); | InterruptHTTPServer(); | ||||
InterruptHTTPRPC(); | InterruptHTTPRPC(); | ||||
▲ Show 20 Lines • Show All 2,311 Lines • ▼ Show 20 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
// At this point we're either in reindex or we've loaded a | // At this point we're either in reindex or we've loaded a | ||||
// useful block tree into mapBlockIndex! | // useful block tree into mapBlockIndex! | ||||
pcoinsdbview.reset(new CCoinsViewDB( | pcoinsdbview.reset(new CCoinsViewDB( | ||||
nCoinDBCache, false, fReset || fReindexChainState)); | nCoinDBCache, false, fReset || fReindexChainState)); | ||||
pcoinscatcher.reset( | pcoinscatcher.reset( | ||||
new CCoinsViewErrorCatcher(pcoinsdbview.get())); | new CCoinsViewErrorCatcher(pcoinsdbview.get())); | ||||
pcoinscatcher->AddReadErrCallback([]() { | |||||
uiInterface.ThreadSafeMessageBox( | |||||
_("Error reading from database, shutting down.") | |||||
.translated, | |||||
"", CClientUIInterface::MSG_ERROR); | |||||
}); | |||||
// If necessary, upgrade from older database format. | // If necessary, upgrade from older database format. | ||||
// This is a no-op if we cleared the coinsviewdb with -reindex | // This is a no-op if we cleared the coinsviewdb with -reindex | ||||
// or -reindex-chainstate | // or -reindex-chainstate | ||||
if (!pcoinsdbview->Upgrade()) { | if (!pcoinsdbview->Upgrade()) { | ||||
strLoadError = | strLoadError = | ||||
_("Error upgrading chainstate database").translated; | _("Error upgrading chainstate database").translated; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 309 Lines • Show Last 20 Lines |