mpv-player / mpv-player/mpv

ao_pipewire: mpv hangs on quit after a second "loadfile replace" when the video output fails to initialize (ao thread spins in epoll_wait on a closed fd)

Open
#18,498 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

os:linux
Dominant language
C
Stars
37k
Forks
3.5k
Avg merge
1d 10h
Merged PRs (30d)
22

Description

mpv Information
mpv v0.41.0 Copyright © 2000-2025 mpv/MPlayer/mplayer2 projects
libplacebo version: v6.338.2
FFmpeg version: 6.1.1-3ubuntu5
FFmpeg library versions:
   libavcodec      60.31.102
   libavdevice     60.3.100
   libavfilter     9.12.100
   libavformat     60.16.100
   libavutil       58.29.100
   libswresample   4.12.100
   libswscale       7.5.100
Other Information
- Linux version: Ubuntu 24.04.5 LTS (Noble), kernel 6.8.0-139-generic #139-Ubuntu SMP PREEMPT_DYNAMIC
- Source of mpv: PPA ppa:ubuntuhandbook1/mpv, package mpv 0.41.0-0ubuntu5~ubuntu2404
- PipeWire: pipewire 1.0.5, libpipewire-0.3-0t64 1.0.5-1ubuntu3.3 (32/64-bit)
- Session: SSH only. XDG_SESSION_TYPE=tty, no DISPLAY / WAYLAND_DISPLAY.
  The local seat0 session owns DRM master, so the default vo=gpu cannot initialize:
      [vo/gpu/drm] Failed to acquire DRM master: Permission denied
      [vo/gpu] Failed initializing any suitable GPU context!
      [cplayer] Video: no video
- Reproduces with --no-config, so user config/scripts are not involved.
Reproduction Steps

Any two video files (with an audio track) work; I tested two 1080p MKVs.
Audio-only files do not reproduce (see the condition table below).

  1. Run from a session where the default video output cannot be initialized
    (here: SSH without a display / DRM master; mpv ends up with Video: no video).

  2. Use the attached script mpv_repro_pipewire_quit_hang.sh:

    ./mpv_repro_pipewire_quit_hang.sh <media1> <media2>
    

    It starts mpv with
    --idle=yes --keep-open=yes --no-config --no-terminal --input-ipc-server=... --log-file=...
    and then sends, over IPC:

    loadfile <media1> replace     # wait 2 s
    loadfile <media2> replace     # wait 2 s
    quit
    
  3. quit replies success, but the mpv process never exits.

Reproduction rate on this machine: 5/5 runs of the script, 7/8 runs of a
parameterized loop (random 0.2–2 s delays between commands). It is a race.

mpv_repro_pipewire_quit_hang.sh

Expected Behavior

quit should terminate the mpv process.

Actual Behavior

The IPC quit command returns success and mpv logs a normal shutdown up to
the end of the player core teardown, but the process stays alive:

  • mpv/ao/pipewire is the only thread in state R (spinning);
  • the main thread is blocked in pw_thread_loop_stop()pthread_join;
  • SIGTERM still terminates the process.

/proc/<pid>/task/*/stat at hang time:

mpv                    state=S wchan=futex_wait_queue
log                    state=S wchan=futex_wait_queue
worker                 state=S wchan=futex_wait_queue
mpv/ao/pipewire        state=R wchan=0
module-rt              state=S wchan=ep_poll
pw-data-loop           state=S wchan=ep_poll

gdb backtrace of the hung process:

Thread 1 (Thread ... "mpv"):
#0  __futex_abstimed_wait_common64 (...)
#2  __GI___futex_abstimed_wait_cancelable64 (...)
#3  __pthread_clockjoin_ex (...) at ./nptl/pthread_join_common.c:102
#4  pw_thread_loop_stop () from /lib/x86_64-linux-gnu/libpipewire-0.3.so.0
#5  ... (mpv, no symbols) ...
#6  ... (mpv, no symbols) ...
#9  main ()

Thread 36 (Thread ... "mpv/ao/pipewire"):
#0  epoll_wait (epfd=0, events=..., maxevents=32, timeout=-1) at epoll_wait.c:30
        sc_ret = -9            # -EBADF
#1  ... libspa-support.so
#2  ... libspa-support.so
#3  ... libpipewire-0.3.so.0
#4  start_thread ...

At hang time fd 0 is closed in the process (it was /dev/null at start), so
the PipeWire thread loop keeps calling epoll_wait() on an invalid fd, gets
EBADF, and busy-loops; pw_thread_loop_stop() can therefore never join it.
(/proc/<pid>/fd list attached; there is no fd/0 entry.)

Log File

Attached (--log-file output of a run that hung). The log ends mid-teardown,
after the player core is gone and while the audio output is being destroyed:

[cplayer] finished playback, success (reason 3)
[cplayer] Running hook: ytdl_hook/on_after_end_file
[cplayer] Exiting... (Quit)
...
[osc] Destroying client handle...

[mpv-pipewire-quit-hang.zip](https://github.com/user-attachments/files/32434729/mpv-pipewire-quit-hang.zip)

### Sample Files

Cannot share the original files, but any video file works. Tested with:

A.mkv : hevc 1920x800 10-bit, dts 48000 Hz 5.1
B.mkv : h264 1920x800, eac3 48000 Hz 5.1


### I carefully read all instruction and confirm that I did the following:

- [x] I tested and confirmed that the issue exists with the [latest release version](https://github.com/mpv-player/mpv/releases/latest) or newer.
- [x] I provided all required information including system and mpv version.
- [x] 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`.
- [x] I produced the log file while the behaviors described in "Actual Behavior" were actively observed.
- [x] I attached the full, untruncated log file.
- [x] I attached the backtrace in the case of a crash.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the ao_pipewire teardown and PipeWire thread-loop shutdown paths, using the attached reproduction script under the documented SSH/no-video-output conditions. Confirm the race around the closed file descriptor and verify that the two-loadfile sequence followed by quit exits cleanly without leaving the audio thread spinning.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
audio-video-rtc
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.