rpc: handle shutdown during long poll and wait methods

The waitTipChanged() now returns nullopt if the node is shutting down.

Previously it would return the last known tip during shutdown, but
this creates an ambiguous circumstance in the scenario where the
node is started and quickly shutdown, before notifications().TipBlock()
is set.

The getblocktemplate, waitfornewblock and waitforblockheight RPC
are updated to handle this. Existing behavior is preserved.

Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
This commit is contained in:
Sjors Provoost
2025-02-19 10:28:43 +01:00
parent a3bf43343f
commit 64a2795fd4
4 changed files with 63 additions and 28 deletions

View File

@@ -46,6 +46,7 @@
#include <memory>
#include <stdint.h>
using interfaces::BlockRef;
using interfaces::BlockTemplate;
using interfaces::Mining;
using node::BlockAssembler;
@@ -801,7 +802,10 @@ static RPCHelpMan getblocktemplate()
{
MillisecondsDouble checktxtime{std::chrono::minutes(1)};
while (tip == hashWatchedChain && IsRPCRunning()) {
tip = miner.waitTipChanged(hashWatchedChain, checktxtime).hash;
std::optional<BlockRef> maybe_tip{miner.waitTipChanged(hashWatchedChain, checktxtime)};
// Node is shutting down
if (!maybe_tip) break;
tip = maybe_tip->hash;
// Timeout: Check transactions for update
// without holding the mempool lock to avoid deadlocks
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)