Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/sv2-tp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,13 @@ MAIN_FUNCTION
registerSignalHandler(SIGINT, HandleSIGTERM);
#endif

while(!g_interrupt) {
while (!g_interrupt && !tp->BackendDisconnected()) {
UninterruptibleSleep(100ms);
}

tp->Interrupt();
tp->StopThreads();
const bool backend_disconnected = tp->BackendDisconnected();

tp.reset();

return EXIT_SUCCESS;
return backend_disconnected ? EXIT_FAILURE : EXIT_SUCCESS;
}
51 changes: 43 additions & 8 deletions src/sv2/template_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ Sv2TemplateProvider::~Sv2TemplateProvider()
m_connman->Interrupt();
m_connman->StopThreads();

Interrupt();
if (!m_backend_disconnected.load()) {
Interrupt();
} else {
m_flag_interrupt_sv2 = true;
}
StopThreads();
}

Expand All @@ -132,16 +136,34 @@ void Sv2TemplateProvider::Interrupt()
{
LOCK(m_tp_mutex);
for (auto& t : GetBlockTemplates()) {
t.second.second->interruptWait();
try {
t.second.second->interruptWait();
} catch (const ipc::Exception& e) {
HandleBackendDisconnect("interruptWait", e);
}
}
}

m_flag_interrupt_sv2 = true;
m_mining.interrupt();
try {
m_mining.interrupt();
} catch (const ipc::Exception& e) {
HandleBackendDisconnect("interrupt", e);
}
// Also interrupt network threads so client handlers can wind down quickly.
if (m_connman) m_connman->Interrupt();
}

void Sv2TemplateProvider::HandleBackendDisconnect(const char* operation, const std::exception& e)
{
const bool first_disconnect = !m_backend_disconnected.exchange(true);
if (first_disconnect) {
LogPrintLevel(BCLog::SV2, BCLog::Level::Error, "Bitcoin Core IPC connection lost during %s: %s\n", operation, e.what());
}
m_flag_interrupt_sv2 = true;
if (m_connman) m_connman->Interrupt();
}

void Sv2TemplateProvider::StopThreads()
{
if (m_thread_sv2_handler.joinable()) {
Expand Down Expand Up @@ -188,7 +210,12 @@ void Sv2TemplateProvider::ThreadSv2Handler()
// TODO: Wait until there's no headers-only branch with more work than our chaintip.
// The current check can still cause us to broadcast a few dozen useless templates
// at startup.
if (!m_mining.isInitialBlockDownload()) break;
try {
if (!m_mining.isInitialBlockDownload()) break;
} catch (ipc::Exception& e) {
HandleBackendDisconnect("isInitialBlockDownload", e);
break;
}
if (log_ibd == 0) {
LogPrintf("Waiting for IBD to complete on %s network before serving templates (this may take a while)\n",
ChainTypeToString(gArgs.GetChainType()));
Expand Down Expand Up @@ -286,7 +313,11 @@ void Sv2TemplateProvider::ThreadSv2ClientHandler(size_t client_id)
if (!prepare_block_create_options(block_create_options)) break;

const auto time_start{SteadyClock::now()};
block_template = m_mining.createNewBlock(block_create_options);
try {
block_template = m_mining.createNewBlock(block_create_options);
} catch (ipc::Exception& e) {
HandleBackendDisconnect("createNewBlock", e);
}
if (!block_template) {
LogPrintLevel(BCLog::SV2, BCLog::Level::Trace, "No new template for client id=%zu, node is shutting down\n",
client_id);
Expand Down Expand Up @@ -352,8 +383,12 @@ void Sv2TemplateProvider::ThreadSv2ClientHandler(size_t client_id)
static_cast<long long>(fee_delta),
client_id);
}

std::shared_ptr<BlockTemplate> tmpl = block_template->waitNext(options);
std::shared_ptr<BlockTemplate> tmpl;
try {
tmpl = block_template->waitNext(options);
} catch (ipc::Exception& e) {
HandleBackendDisconnect("waitNext", e);
}
// The client may have disconnected during the wait, check now to avoid
// a spurious IPC call and confusing log statements.
{
Expand Down Expand Up @@ -405,7 +440,7 @@ void Sv2TemplateProvider::ThreadSv2ClientHandler(size_t client_id)
std::this_thread::sleep_for(50ms);
}
}
} catch (const std::exception& e) {
} catch (std::exception& e) {
LogPrintLevel(BCLog::SV2, BCLog::Level::Trace,
"Client thread for id=%zu exiting after exception: %s\n",
client_id, e.what());
Expand Down
11 changes: 11 additions & 0 deletions src/sv2/template_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <util/time.h>
#include <streams.h>
#include <memory>
#include <atomic>

using interfaces::BlockTemplate;

Expand Down Expand Up @@ -111,6 +112,11 @@ class Sv2TemplateProvider : public Sv2EventsInterface
using BlockTemplateCache = std::map<uint64_t, std::pair<uint256, std::shared_ptr<BlockTemplate>>>;
BlockTemplateCache m_block_template_cache GUARDED_BY(m_tp_mutex);

/**
* flag to check if the backend has been disconnected or not
*/
std::atomic<bool> m_backend_disconnected{false};

public:
explicit Sv2TemplateProvider(interfaces::Mining& mining);

Expand Down Expand Up @@ -168,6 +174,9 @@ class Sv2TemplateProvider : public Sv2EventsInterface
/* Block templates that connected clients may be working on */
BlockTemplateCache& GetBlockTemplates() EXCLUSIVE_LOCKS_REQUIRED(m_tp_mutex) { return m_block_template_cache; }

// Accessor to get the backend disconnected state
bool BackendDisconnected() const {return m_backend_disconnected.load();}

private:

/* Forget templates from before the last block, but with a few seconds margin. */
Expand All @@ -189,6 +198,8 @@ class Sv2TemplateProvider : public Sv2EventsInterface
*/
[[nodiscard]] bool SendWork(Sv2Client& client, uint64_t template_id, BlockTemplate& block_template, bool future_template);

void HandleBackendDisconnect(const char* operation, const std::exception& e);

};

#endif // BITCOIN_SV2_TEMPLATE_PROVIDER_H
Loading