From 9c2161ead78db5e527c88c52cf772db169051e6a Mon Sep 17 00:00:00 2001 From: Mark Constable Date: Fri, 20 Mar 2026 13:27:47 +1000 Subject: [PATCH] fix(pulse): use blocking iterate to prevent busy-spin on boot When pipewire-pulse is not yet ready at boot, pa_mainloop_iterate(false) returns immediately, causing a tight 100% CPU loop. This cascades into cosmic-osd spinning and Firefox/Thunderbird becoming unresponsive. Switch to iterate(true) (blocking) so the loop sleeps until there is an event to process. Also handle Failed/Terminated context states explicitly instead of looping forever. Co-Authored-By: Claude Opus 4.6 (1M context) --- subscriptions/pulse/src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/subscriptions/pulse/src/lib.rs b/subscriptions/pulse/src/lib.rs index 4220765db..e877a4e21 100644 --- a/subscriptions/pulse/src/lib.rs +++ b/subscriptions/pulse/src/lib.rs @@ -77,12 +77,15 @@ pub fn thread(sender: futures::channel::mpsc::Sender) { let _ = context.connect(None, FlagSet::NOFAIL, None); + // Wait for the PulseAudio context to become ready. + // Use blocking iteration to avoid busy-spinning if the server + // is not yet available (e.g. pipewire-pulse starting concurrently). loop { if sender.is_closed() { return; } - match main_loop.iterate(false) { + match main_loop.iterate(true) { IterateResult::Success(_) => {} IterateResult::Err(_e) => { return; @@ -92,8 +95,13 @@ pub fn thread(sender: futures::channel::mpsc::Sender) { } } - if context.get_state() == State::Ready { - break; + match context.get_state() { + State::Ready => break, + State::Failed | State::Terminated => { + log::error!("PulseAudio context connection failed"); + return; + } + _ => {} // Unconnected, Connecting, Authorizing, SettingName — keep waiting } }