Merge bitcoin/bitcoin#27708: Return EXIT_FAILURE on post-init fatal errors

61c569ab60 refactor: decouple early return commands from AppInit (furszy)
4927167f85 gui: return EXIT_FAILURE on post-init fatal errors (furszy)
3b2c61e819 Return EXIT_FAILURE on post-init fatal errors (furszy)
3c06926cf2 refactor: index: use `AbortNode` in fatal error helper (Sebastian Falbesoner)
9ddf7e03a3 move ThreadImport ABC error to use AbortNode (furszy)

Pull request description:

  It seems odd to return `EXIT_SUCCESS` when the node aborted execution due a fatal internal error
  or any post-init problem that triggers an unrequested shutdown.

  e.g. blocks or coins db I/O errors, disconnect block failure, failure during thread import (external
  blocks loading process error), among others.

ACKs for top commit:
  TheCharlatan:
    ACK 61c569ab60
  ryanofsky:
    Code review ACK 61c569ab60
  pinheadmz:
    ACK 61c569ab60
  theStack:
    Code-review ACK 61c569ab60

Tree-SHA512: 18a59c3acc1c6d12cbc74a20a401e89659740c6477fccb59070c9f97922dfe588468e9e5eef56c5f395762187c34179a5e3954aa5b844787fa13da2e666c63d3
This commit is contained in:
Ryan Ofsky
2023-06-12 12:13:55 -04:00
14 changed files with 85 additions and 56 deletions

View File

@@ -928,8 +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)) {
LogPrintf("Failed to connect best block (%s)\n", state.ToString());
StartShutdown();
AbortNode(strprintf("Failed to connect best block (%s)", state.ToString()));
return;
}
}

View File

@@ -7,7 +7,9 @@
#include <kernel/context.h>
#include <atomic>
#include <cassert>
#include <cstdlib>
#include <functional>
#include <memory>
#include <vector>
@@ -65,6 +67,7 @@ struct NodeContext {
std::unique_ptr<CScheduler> scheduler;
std::function<void()> rpc_interruption_point = [] {};
std::unique_ptr<KernelNotifications> notifications;
std::atomic<int> exit_status{EXIT_SUCCESS};
//! Declare default constructor and destructor that are not inline, so code
//! instantiating the NodeContext struct doesn't need to #include class

View File

@@ -89,10 +89,11 @@ public:
void initLogging() override { InitLogging(args()); }
void initParameterInteraction() override { InitParameterInteraction(args()); }
bilingual_str getWarnings() override { return GetWarnings(true); }
int getExitStatus() override { return Assert(m_context)->exit_status.load(); }
uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); }
bool baseInitialize() override
{
if (!AppInitBasicSetup(args())) return false;
if (!AppInitBasicSetup(args(), Assert(context())->exit_status)) return false;
if (!AppInitParameterInteraction(args(), /*use_syscall_sandbox=*/false)) return false;
m_context->kernel = std::make_unique<kernel::Context>();
@@ -105,7 +106,10 @@ public:
}
bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override
{
return AppInitMain(*m_context, tip_info);
if (AppInitMain(*m_context, tip_info)) return true;
// Error during initialization, set exit status before continue
m_context->exit_status.store(EXIT_FAILURE);
return false;
}
void appShutdown() override
{