From 484f4f26e628122ee2435fd4a98ef94e7bd20970 Mon Sep 17 00:00:00 2001 From: Yeji Han Date: Mon, 8 Jun 2026 13:56:14 +0900 Subject: [PATCH 1/3] fix(cbf): shut down chain source cleanly - Implement CBF requester shutdown and mark runtime status stopped on clean exit. - Route generic chain source stop calls to the CBF backend. AI-assisted-by: OpenAI Codex --- src/chain/cbf.rs | 19 ++++++++++++++++++- src/chain/mod.rs | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/chain/cbf.rs b/src/chain/cbf.rs index d9d70cc5c..037e03777 100644 --- a/src/chain/cbf.rs +++ b/src/chain/cbf.rs @@ -248,6 +248,7 @@ impl CbfChainSource { match current_node.run().await { Ok(()) => { log_info!(restart_logger, "CBF node shut down cleanly."); + *restart_status.lock().expect("lock") = CbfRuntimeStatus::Stopped; break; }, Err(e) => { @@ -306,7 +307,23 @@ impl CbfChainSource { } pub(crate) fn stop(&self) { - todo!(); + let requester = { + let mut status = self.cbf_runtime_status.lock().expect("lock"); + match &*status { + CbfRuntimeStatus::Started { requester } => { + let requester = requester.clone(); + *status = CbfRuntimeStatus::Stopped; + Some(requester) + }, + CbfRuntimeStatus::Stopped => None, + } + }; + + if let Some(requester) = requester { + if let Err(e) = requester.shutdown() { + log_error!(self.logger, "Failed to shut down CBF node: {:?}", e); + } + } } async fn process_info_messages(mut info_rx: mpsc::Receiver, logger: Arc) { diff --git a/src/chain/mod.rs b/src/chain/mod.rs index ed5630206..e37c55ea7 100644 --- a/src/chain/mod.rs +++ b/src/chain/mod.rs @@ -246,6 +246,7 @@ impl ChainSource { pub(crate) fn stop(&self) { match &self.kind { ChainSourceKind::Electrum(electrum_chain_source) => electrum_chain_source.stop(), + ChainSourceKind::Cbf(cbf_chain_source) => cbf_chain_source.stop(), _ => { // Nothing to do for other chain sources. }, From 1e26f79fd3916945ae43aff698df1debc9985eb7 Mon Sep 17 00:00:00 2001 From: Yeji Han Date: Fri, 22 May 2026 13:05:22 +0900 Subject: [PATCH 2/3] fix(cbf): stop chain source before waiting on tasks - Stop runtime-dependent chain sources before waiting for non-cancellable background tasks. - Allow the CBF requester shutdown to unblock the node run loop during Node::stop. --- src/lib.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 374614c4b..2a11ec359 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -740,13 +740,15 @@ impl Node { self.peer_manager.disconnect_all_peers(); log_debug!(self.logger, "Disconnected all network peers."); - // Wait until non-cancellable background tasks (mod LDK's background processor) are done. - self.runtime.wait_on_background_tasks(); - - // Stop any runtime-dependant chain sources. + // Stop any runtime-dependant chain sources before waiting on non-cancellable + // background tasks. Some chain sources own background tasks that only exit + // after their client/requester is shut down. self.chain_source.stop(); log_debug!(self.logger, "Stopped chain sources."); + // Wait until non-cancellable background tasks (mod LDK's background processor) are done. + self.runtime.wait_on_background_tasks(); + // Stop the background processor. self.background_processor_stop_sender .send(()) From 720a3e8f38ac54b95b81106cefd7c648a8abcb6e Mon Sep 17 00:00:00 2001 From: Yeji Han Date: Tue, 9 Jun 2026 05:05:38 +0900 Subject: [PATCH 3/3] fix(cbf): abort restart when stopped during backoff - Check CBF runtime status before publishing a rebuilt requester after restart backoff. - Shut down the newly built requester and exit the restart loop if stop() ran during the backoff. --- src/chain/cbf.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/chain/cbf.rs b/src/chain/cbf.rs index 037e03777..baca0ced5 100644 --- a/src/chain/cbf.rs +++ b/src/chain/cbf.rs @@ -293,8 +293,18 @@ impl CbfChainSource { event_rx: new_event_rx, } = new_client; - *restart_status.lock().expect("lock") = - CbfRuntimeStatus::Started { requester: new_requester }; + { + let mut status = restart_status.lock().expect("lock"); + if matches!(*status, CbfRuntimeStatus::Stopped) { + let _ = new_requester.shutdown(); + log_info!( + restart_logger, + "CBF restart aborted: stop() called during backoff." + ); + break; + } + *status = CbfRuntimeStatus::Started { requester: new_requester }; + } current_node = new_node; current_info_rx = new_info_rx;