From 928d398e928644a7fbdb05f68ac59dc9ef378fa7 Mon Sep 17 00:00:00 2001 From: dengzhongyuan Date: Thu, 26 Mar 2026 20:27:08 +0800 Subject: [PATCH] ao/pulse: fix ao_drain hang when underrun makes buf_diff negative With prebuf=0, on underrun read_index overtakes write_index, making buf_diff negative. Passing it to pa_bytes_to_usec() (uint64_t) overflows and causes ao_drain() to hang forever via an infinite mp_cond_timedwait(). Fixes: 17651 --- audio/out/ao_pulse.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index 6b9b141d99af0..995d48fe4349e 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -584,8 +584,11 @@ static double get_delay_hackfixed(struct ao *ao) GENERIC_ERR_MSG("pa_stream_get_sample_spec() failed"); return 0; } - // data left in PulseAudio's main buffers (not written to sink yet) - int64_t latency = pa_bytes_to_usec(ti->write_index - ti->read_index, ss); + // data left in PulseAudio's main buffers (not written to sink yet). + // With prebuf=0, an underrun may make write_index < read_index (negative buf_diff), + // which breaks the pa_bytes_to_usec() conversion and can overflow into an infinite drain wait. + int64_t buf_diff = ti->write_index - ti->read_index; + int64_t latency = buf_diff > 0 ? pa_bytes_to_usec(buf_diff, ss) : 0; // since this info may be from a while ago, playback has progressed since latency -= ti->transport_usec; // data already moved from buffers to sink, but not played yet