Skip to content

Commit

Permalink
merge bitcoin#16355: move CCoinsViewErrorCatcher out of init.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
kwvg committed Oct 16, 2021
1 parent f6215ab commit 01e8c0d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 25 deletions.
17 changes: 17 additions & 0 deletions src/coins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <coins.h>

#include <consensus/consensus.h>
#include <logging.h>
#include <random.h>
#include <version.h>

Expand Down Expand Up @@ -268,3 +269,19 @@ const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid)
}
return coinEmpty;
}

bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) const {
try {
return CCoinsViewBacked::GetCoin(outpoint, coin);
} catch(const std::runtime_error& e) {
for (auto f : m_err_callbacks) {
f();
}
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.
std::abort();
}
}
25 changes: 25 additions & 0 deletions src/coins.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <assert.h>
#include <stdint.h>

#include <functional>
#include <unordered_map>

/**
Expand Down Expand Up @@ -348,4 +349,28 @@ void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool
//! lookups to database, so it should be used with care.
const Coin& AccessByTxid(const CCoinsViewCache& cache, const uint256& txid);

/**
* 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.
*
* Writes do not need similar protection, as failure to write is handled by the caller.
*/
class CCoinsViewErrorCatcher final : public CCoinsViewBacked
{
public:
explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {}

void AddReadErrCallback(std::function<void()> f) {
m_err_callbacks.emplace_back(std::move(f));
}

bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;

private:
/** A list of callbacks to execute upon leveldb read error. */
std::vector<std::function<void()>> m_err_callbacks;

};

#endif // BITCOIN_COINS_H
31 changes: 6 additions & 25 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <chain.h>
#include <chainparams.h>
#include <checkpoints.h>
#include <coins.h>
#include <node/coinstats.h>
#include <compat/sanity.h>
#include <consensus/validation.h>
Expand Down Expand Up @@ -180,31 +181,6 @@ static fs::path GetPidFile()
// 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 dashd, and dash-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."), "", 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<ECCVerifyHandle> globalVerifyHandle;

Expand Down Expand Up @@ -2071,6 +2047,11 @@ bool AppInitMain()

pcoinsdbview.reset(new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState));
pcoinscatcher.reset(new CCoinsViewErrorCatcher(pcoinsdbview.get()));
pcoinscatcher->AddReadErrCallback([]() {
uiInterface.ThreadSafeMessageBox(
_("Error reading from database, shutting down."),
"", CClientUIInterface::MSG_ERROR);
});

// If necessary, upgrade from older database format.
// This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
Expand Down

0 comments on commit 01e8c0d

Please sign in to comment.