From d1be71ff47a510e87807438e03991649053653ab Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Mon, 2 Mar 2026 20:02:25 +0100 Subject: [PATCH] Fix stream header invalidation and source task cleanup Invalidate the cached OGG header immediately when restarting the FLAC encoder to prevent clients from receiving stale data. Also improve the player source cleanup by draining the chunk receiver and adding a timeout when waiting for the emit task to finish, preventing potential hangs when the downstream pipeline is saturated. --- pmoaudio-ext/src/sinks/streaming_sink_common.rs | 5 +++++ pmoaudio-ext/src/sources/player_source.rs | 13 +++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pmoaudio-ext/src/sinks/streaming_sink_common.rs b/pmoaudio-ext/src/sinks/streaming_sink_common.rs index e2e9142f..952fdd48 100644 --- a/pmoaudio-ext/src/sinks/streaming_sink_common.rs +++ b/pmoaudio-ext/src/sinks/streaming_sink_common.rs @@ -490,6 +490,11 @@ impl SharedSinkContext { debug!("Restarting FLAC encoder for new track"); + // Invalider le header en cache immédiatement : tout nouveau client qui se connecte + // pendant le restart attendra (Poll::Pending) jusqu'à ce que le nouveau header OGG + // soit prêt, évitant qu'il reçoive l'ancien header suivi des nouvelles données. + *self.header.write().await = None; + let last_timestamp = *self.current_timestamp.read().await; debug!("Last timestamp before restart: {:.3}s", last_timestamp); diff --git a/pmoaudio-ext/src/sources/player_source.rs b/pmoaudio-ext/src/sources/player_source.rs index 4e81fe2b..06d4a428 100644 --- a/pmoaudio-ext/src/sources/player_source.rs +++ b/pmoaudio-ext/src/sources/player_source.rs @@ -469,8 +469,17 @@ impl PlayerSourceLogic { } } - // Attendre que la tâche source se termine proprement - let _ = emit_task.await; + // Vider chunk_rx pour débloquer emit_task si elle est bloquée sur un send + // (peut arriver si le pipeline en aval est saturé au moment du cancel) + while chunk_rx.try_recv().is_ok() {} + + // Attendre que la tâche source se termine, avec timeout de sécurité + tokio::select! { + _ = emit_task => {} + _ = tokio::time::sleep(std::time::Duration::from_millis(500)) => { + warn!("PlayerSource: emit_task did not finish in time after cancel"); + } + } result } }