kernel: Add fatalError method to notifications

FatalError replaces what previously was the AbortNode function in
shutdown.cpp.

This commit is part of the libbitcoinkernel project and further removes
the shutdown's and, more generally, the kernel library's dependency on
interface_ui with a kernel notification method. By removing interface_ui
from the kernel library, its dependency on boost is reduced to just
boost::multi_index. At the same time it also takes a step towards
de-globalising the interrupt infrastructure.

Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
Co-authored-by: TheCharlatan <seb.kung@gmail.com>
This commit is contained in:
TheCharlatan
2023-05-09 11:15:46 +02:00
parent 7320db96f8
commit 6eb33bd0c2
19 changed files with 128 additions and 90 deletions

27
src/node/abort.cpp Normal file
View File

@@ -0,0 +1,27 @@
// Copyright (c) 2023 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <node/abort.h>
#include <logging.h>
#include <node/interface_ui.h>
#include <shutdown.h>
#include <util/translation.h>
#include <warnings.h>
#include <atomic>
#include <cstdlib>
#include <string>
namespace node {
void AbortNode(std::atomic<int>& exit_status, const std::string& debug_message, const bilingual_str& user_message, bool shutdown)
{
SetMiscWarning(Untranslated(debug_message));
LogPrintf("*** %s\n", debug_message);
InitError(user_message.empty() ? _("A fatal internal error occurred, see debug.log for details") : user_message);
exit_status.store(EXIT_FAILURE);
if (shutdown) StartShutdown();
}
} // namespace node

17
src/node/abort.h Normal file
View File

@@ -0,0 +1,17 @@
// Copyright (c) 2023 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_NODE_ABORT_H
#define BITCOIN_NODE_ABORT_H
#include <util/translation.h>
#include <atomic>
#include <string>
namespace node {
void AbortNode(std::atomic<int>& exit_status, const std::string& debug_message, const bilingual_str& user_message = {}, bool shutdown = true);
} // namespace node
#endif // BITCOIN_NODE_ABORT_H

View File

@@ -659,7 +659,8 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
bool out_of_space;
size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space);
if (out_of_space) {
return AbortNode("Disk space is too low!", _("Disk space is too low!"));
m_opts.notifications.fatalError("Disk space is too low!", _("Disk space is too low!"));
return false;
}
if (bytes_allocated != 0 && IsPruneMode()) {
m_check_for_pruning = true;
@@ -683,7 +684,7 @@ bool BlockManager::FindUndoPos(BlockValidationState& state, int nFile, FlatFileP
bool out_of_space;
size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space);
if (out_of_space) {
return AbortNode(state, "Disk space is too low!", _("Disk space is too low!"));
return FatalError(m_opts.notifications, state, "Disk space is too low!", _("Disk space is too low!"));
}
if (bytes_allocated != 0 && IsPruneMode()) {
m_check_for_pruning = true;
@@ -725,7 +726,7 @@ bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValid
return error("ConnectBlock(): FindUndoPos failed");
}
if (!UndoWriteToDisk(blockundo, _pos, block.pprev->GetBlockHash(), GetParams().MessageStart())) {
return AbortNode(state, "Failed to write undo data");
return FatalError(m_opts.notifications, state, "Failed to write undo data");
}
// rev files are written in block height order, whereas blk files are written as blocks come in (often out of order)
// we want to flush the rev (undo) file once we've written the last block, which is indicated by the last height
@@ -843,7 +844,7 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CCha
}
if (!position_known) {
if (!WriteBlockToDisk(block, blockPos, GetParams().MessageStart())) {
AbortNode("Failed to write block");
m_opts.notifications.fatalError("Failed to write block");
return FlatFilePos();
}
}
@@ -927,7 +928,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
for (Chainstate* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
BlockValidationState state;
if (!chainstate->ActivateBestChain(state, nullptr)) {
AbortNode(strprintf("Failed to connect best block (%s)", state.ToString()));
chainman.GetNotifications().fatalError(strprintf("Failed to connect best block (%s)", state.ToString()));
return;
}
}

View File

@@ -10,8 +10,12 @@
#include <common/args.h>
#include <common/system.h>
#include <kernel/context.h>
#include <logging.h>
#include <node/abort.h>
#include <node/interface_ui.h>
#include <shutdown.h>
#include <util/check.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/translation.h>
@@ -75,7 +79,12 @@ void KernelNotifications::warning(const bilingual_str& warning)
void KernelNotifications::flushError(const std::string& debug_message)
{
AbortNode(debug_message);
AbortNode(m_exit_status, debug_message);
}
void KernelNotifications::fatalError(const std::string& debug_message, const bilingual_str& user_message)
{
node::AbortNode(m_exit_status, debug_message, user_message, m_shutdown_on_fatal_error);
}
} // namespace node

View File

@@ -7,6 +7,7 @@
#include <kernel/notifications_interface.h>
#include <atomic>
#include <cstdint>
#include <string>
@@ -18,6 +19,8 @@ namespace node {
class KernelNotifications : public kernel::Notifications
{
public:
KernelNotifications(std::atomic<int>& exit_status) : m_exit_status{exit_status} {}
void blockTip(SynchronizationState state, CBlockIndex& index) override;
void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) override;
@@ -27,6 +30,13 @@ public:
void warning(const bilingual_str& warning) override;
void flushError(const std::string& debug_message) override;
void fatalError(const std::string& debug_message, const bilingual_str& user_message = {}) override;
//! Useful for tests, can be set to false to avoid shutdown on fatal error.
bool m_shutdown_on_fatal_error{true};
private:
std::atomic<int>& m_exit_status;
};
} // namespace node