Skip to content

Commit 04265ba

Browse files
committed
Merge bitcoin#26331: Implement CCoinsViewErrorCatcher::HaveCoin and check disk space periodically
ed52e71 Periodically check disk space to avoid corruption (Aurèle Oulès) 7fe537f Implement CCoinsViewErrorCatcher::HaveCoin (Aurèle Oulès) Pull request description: Attempt to fix bitcoin#26112. As suggested by sipa in bitcoin#26112 (comment): > CCoinsViewErrorCatcher, the wrapper class used around CCoinsViewDB that's supposed to detect these problems and forcefully exit the application, has an override for GetCoins. But in CheckTxInputs, HaveInputs is first invoked, which on its turn calls HaveCoin. HaveCoin is implemented in CCoinsViewDB, but not in CCoinsViewErrorCatcher, and thus the disk read exception escapes. > A solution may be to just add an override for HaveCoin in CCoinsViewErrorCatcher. I implemented `CCoinsViewErrorCatcher::HaveCoin` and also added a periodic disk space check that shutdowns the node if there is not enough space left on disk, the minimum here is 50MB. For reviewers, it's possible to saturate disk space to test the PR by creating large files with `fallocate -l 50G test.bin` ACKs for top commit: achow101: ACK ed52e71 w0xlt: Code Review ACK bitcoin@ed52e71 sipa: utACK ed52e71 Tree-SHA512: 456aa7b996023df42b4fbb5158ee429d9abf7374b7b1ec129b21aea1188ad19be8da4ae8e0edd90b85b7a3042b8e44e17d3742e33808a4234d5ddbe9bcef1b78
2 parents 4e7442e + ed52e71 commit 04265ba

File tree

3 files changed

+23
-3
lines changed

3 files changed

+23
-3
lines changed

src/coins.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,13 @@ const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid)
353353
return coinEmpty;
354354
}
355355

356-
bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) const {
356+
template <typename Func>
357+
static bool ExecuteBackedWrapper(Func func, const std::vector<std::function<void()>>& err_callbacks)
358+
{
357359
try {
358-
return CCoinsViewBacked::GetCoin(outpoint, coin);
360+
return func();
359361
} catch(const std::runtime_error& e) {
360-
for (const auto& f : m_err_callbacks) {
362+
for (const auto& f : err_callbacks) {
361363
f();
362364
}
363365
LogPrintf("Error reading from database: %s\n", e.what());
@@ -368,3 +370,11 @@ bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) cons
368370
std::abort();
369371
}
370372
}
373+
374+
bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) const {
375+
return ExecuteBackedWrapper([&]() { return CCoinsViewBacked::GetCoin(outpoint, coin); }, m_err_callbacks);
376+
}
377+
378+
bool CCoinsViewErrorCatcher::HaveCoin(const COutPoint &outpoint) const {
379+
return ExecuteBackedWrapper([&]() { return CCoinsViewBacked::HaveCoin(outpoint); }, m_err_callbacks);
380+
}

src/coins.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ class CCoinsViewErrorCatcher final : public CCoinsViewBacked
383383
}
384384

385385
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
386+
bool HaveCoin(const COutPoint &outpoint) const override;
386387

387388
private:
388389
/** A list of callbacks to execute upon leveldb read error. */

src/init.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,15 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
11381138
RandAddPeriodic();
11391139
}, std::chrono::minutes{1});
11401140

1141+
// Check disk space every 5 minutes to avoid db corruption.
1142+
node.scheduler->scheduleEvery([&args]{
1143+
constexpr uint64_t min_disk_space = 50 << 20; // 50 MB
1144+
if (!CheckDiskSpace(args.GetBlocksDirPath(), min_disk_space)) {
1145+
LogPrintf("Shutting down due to lack of disk space!\n");
1146+
StartShutdown();
1147+
}
1148+
}, std::chrono::minutes{5});
1149+
11411150
GetMainSignals().RegisterBackgroundSignalScheduler(*node.scheduler);
11421151

11431152
// Create client interfaces for wallets that are supposed to be loaded

0 commit comments

Comments
 (0)