From b7550709fc191853d05658a05529b1073d71d4fb Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Wed, 20 Aug 2025 09:14:20 +0200 Subject: [PATCH 1/2] Introduce separate stop signal for background processor Previously, we'd use the same stop signal for the background processor as for all other background tasks which could result in the BP getting stopped while other tasks are still produced changes that needed to be processed before shutdown. Here we introduce a separate stop signal for LDK's background processor, ensuring we first shutdown everything else and disconnect all peers before finally sending the BP shutdown signal and awaiting its shutdown. --- src/builder.rs | 2 ++ src/lib.rs | 32 +++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 7f15cced6..0ef3434d6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1668,11 +1668,13 @@ fn build_with_store_internal( }; let (stop_sender, _) = tokio::sync::watch::channel(()); + let (background_processor_stop_sender, _) = tokio::sync::watch::channel(()); let is_running = Arc::new(RwLock::new(false)); Ok(Node { runtime, stop_sender, + background_processor_stop_sender, config, wallet, chain_source, diff --git a/src/lib.rs b/src/lib.rs index 1604d1b46..e77a2f8a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -180,6 +180,7 @@ uniffi::include_scaffolding!("ldk_node"); pub struct Node { runtime: Arc, stop_sender: tokio::sync::watch::Sender<()>, + background_processor_stop_sender: tokio::sync::watch::Sender<()>, config: Arc, wallet: Arc, chain_source: Arc, @@ -525,7 +526,7 @@ impl Node { let background_logger = Arc::clone(&self.logger); let background_error_logger = Arc::clone(&self.logger); let background_scorer = Arc::clone(&self.scorer); - let stop_bp = self.stop_sender.subscribe(); + let stop_bp = self.background_processor_stop_sender.subscribe(); let sleeper_logger = Arc::clone(&self.logger); let sleeper = move |d| { let mut stop = stop_bp.clone(); @@ -607,18 +608,20 @@ impl Node { // Stop any runtime-dependant chain sources. self.chain_source.stop(); - // Stop the runtime. - match self.stop_sender.send(()) { - Ok(_) => log_trace!(self.logger, "Sent shutdown signal to background tasks."), - Err(e) => { + // Stop background tasks. + self.stop_sender + .send(()) + .map(|_| { + log_trace!(self.logger, "Sent shutdown signal to background tasks."); + }) + .unwrap_or_else(|e| { log_error!( self.logger, "Failed to send shutdown signal. This should never happen: {}", e ); debug_assert!(false); - }, - } + }); // Cancel cancellable background tasks self.runtime.abort_cancellable_background_tasks(); @@ -634,6 +637,21 @@ impl Node { // 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(()) + .map(|_| { + log_trace!(self.logger, "Sent shutdown signal to background processor."); + }) + .unwrap_or_else(|e| { + log_error!( + self.logger, + "Failed to send shutdown signal. This should never happen: {}", + e + ); + debug_assert!(false); + }); + // Finally, wait until background processing stopped, at least until a timeout is reached. self.runtime.wait_on_background_processor_task(); From c428c4ca8a16cbf0ed377560b7f0bdbff4b1742c Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Wed, 20 Aug 2025 09:17:43 +0200 Subject: [PATCH 2/2] Remove duplicate call to `chain_source.stop()` This was introduced during a rebase. Here we simply drop the redundant call. --- src/lib.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e77a2f8a6..da86fce73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -605,9 +605,6 @@ impl Node { log_info!(self.logger, "Shutting down LDK Node with node ID {}...", self.node_id()); - // Stop any runtime-dependant chain sources. - self.chain_source.stop(); - // Stop background tasks. self.stop_sender .send(()) @@ -630,13 +627,13 @@ 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. 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(())