From 5bae97e9d2bd47b6beccfbc1822e33c011dee574 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Thu, 8 Aug 2024 08:24:01 -0700 Subject: [PATCH] ready_queue: avoid busy loop in maintainer when shutting down When we are shutting down, the ShutdownSubscription will initially wake us up from a sleep, then will always be immediately signalled for the rest of the lifetime of the program. Since we use it being signalled as a wakeup, it will effectively cause a busy loop where we never sleep the ready queue while we wait for the queue to wrap up. Avoid that by ignoring the ShutdownSubscription once we realize that we are shutting down. A similar situation can occur with refreshing the configuration; when shutting down, we can simply ignore that. --- crates/kumod/src/ready_queue.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/crates/kumod/src/ready_queue.rs b/crates/kumod/src/ready_queue.rs index 41958ca0..9ab66df5 100644 --- a/crates/kumod/src/ready_queue.rs +++ b/crates/kumod/src/ready_queue.rs @@ -308,16 +308,33 @@ impl ReadyQueueManager { let mut last_config_refresh = tokio::time::Instant::now(); let mut reap_deadline = None; let mut done_abort = false; + let mut shutting_down = false; let queue = ReadyQueueManager::get_by_name(&name).ok_or_else(|| { anyhow::anyhow!("ready_queue {name} not found when starting up maintainer_task") })?; loop { + let wait_for_shutdown = async { + if shutting_down { + tokio::time::sleep(Duration::from_secs(1)).await + } else { + shutdown.shutting_down().await + } + }; + + let wait_for_config_refresh = async { + if shutting_down { + tokio::time::sleep(Duration::from_secs(1)).await + } else { + tokio::time::sleep_until(last_config_refresh + interval).await + } + }; + tokio::select! { - _ = tokio::time::sleep_until(last_config_refresh + interval) => { - }, - _ = shutdown.shutting_down() => { + _ = wait_for_config_refresh => {}, + _ = wait_for_shutdown => { + shutting_down = true; interval = Duration::from_secs(1); if reap_deadline.is_none() { let duration = queue.path_config.borrow().client_timeouts.total_message_send_duration();