ao/pulse: ao_drain() hangs forever on LoongArch when PulseAudio underrun produces negative buf_diff
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 37k
- Forks
- 3.5k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 22
Description
mpv Information
uos@uos-PC:~/proj/deepin-movie-reborn$ mpv --version
mpv 0.38.0 Copyright © 2000-2024 mpv/MPlayer/mplayer2 projects
libplacebo version: v6.338.2
FFmpeg version: 6.1.1-2deepin9
FFmpeg library versions:
libavutil 58.29.100
libavcodec 60.31.102
libavformat 60.16.100
libswscale 7.5.100
libavfilter 9.12.100
libswresample 4.12.100
Other Information
- Linux version:
- Kernel Version:
- GPU Model:
- Mesa/GPU Driver Version:
- Window Manager and Version:
- Source of mpv:
- Latest known working version:
- Issue started after the following happened:
Reproduction Steps
- Use a LoongArch64 machine with PulseAudio as the audio backend
- Play any video file to completion: mpv test.mp4
- Wait for playback to finish naturally (do not press q)
- Observe that the mpv process does not exit and hangs permanently
Expected Behavior
mpv exits cleanly after playback finishes.
Actual Behavior
mpv hangs permanently after playback ends. The process is frozen (0% CPU,
no response to input) and must be killed manually with SIGKILL.
Log File
Thread 11 (mpv core):
#6 ao_drain (ao=...) at ../audio/out/buffer.c:484
#7 uninit_audio_out (...) at ../player/audio.c:245
#8 idle_loop (...) at ../player/playloop.c:1308
Thread 19 (ao thread):
#3 mp_cond_timedwait (timeout=9223372036854775807 /* INT64_MAX */, ...)
at ../audio/out/buffer.c
Root cause analysis:
With prebuf=0 (set by mpv), PulseAudio documents that on underrun
read_index overtakes write_index. In get_delay_hackfixed():
int64_t latency = pa_bytes_to_usec(ti->write_index - ti->read_index, ss);
The subtraction produces a negative int64_t. Passing it to pa_bytes_to_usec()
(which takes uint64_t) triggers implicit conversion to ~2^64, producing a
latency on the order of 1e8 seconds. This flows into ao_drain():
mp_cond_timedwait(&p->wakeup, &p->lock,
MP_TIME_S_TO_NS(MPMAX(delay, 0) + 0.25))
MP_TIME_S_TO_NS(1e8) ≈ 1e17 ns, which exceeds the 1000-day threshold in
mp_cond_timedwait() (threads-posix.h), causing it to call pthread_cond_wait()
instead — an infinite wait.
On x86_64 this code path is never reached because underflow_cb() fires
and clears priv->playing before ao_drain() enters its wait loop, so
ao_drain() exits without calling get_delay_hackfixed(). On LoongArch,
underflow_cb() does not fire in time, exposing the overflow bug.
Fix: guard pa_bytes_to_usec() against negative input in get_delay_hackfixed().
Environment: LoongArch64, PulseAudio, mpv 0.38.0
Sample Files
No response
I carefully read all instruction and confirm that I did the following:
- I tested and confirmed that the issue exists with the latest release version or newer.
- I provided all required information including system and mpv version.
- I produced the log file with the exact same set of files, parameters, and conditions used in "Reproduction Steps", with the addition of
--log-file=output.txt. - I produced the log file while the behaviors described in "Actual Behavior" were actively observed.
- I attached the full, untruncated log file.
- I attached the backtrace in the case of a crash.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in audio/out/buffer.c at get_delay_hackfixed() and ao_drain(), then review the PulseAudio underrun behavior described in the issue. Check threads-posix.h to understand the timed-wait threshold. Done means playback exits normally on LoongArch64 after a PulseAudio underrun, without introducing an oversized delay or indefinite wait.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- audio-video-rtc
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100