Skip to content

Fix macOS threading deadlock in _event_generator (issue #61)#314

Open
copernicusjones wants to merge 1 commit into
jaseg:mainfrom
copernicusjones:fix-macos-threading-deadlock
Open

Fix macOS threading deadlock in _event_generator (issue #61)#314
copernicusjones wants to merge 1 commit into
jaseg:mainfrom
copernicusjones:fix-macos-threading-deadlock

Conversation

@copernicusjones

Copy link
Copy Markdown

Summary

Fixes the deadlock described in issue #61 where wait_for_playback() hangs forever on macOS.

Root Cause

On macOS, mpv's Cocoa backend requires the main thread for its event loop. The previous code used mpv_wait_event(handle, -1) (infinite timeout) in a background Python thread, which caused a deadlock:

  1. Main thread blocks on result.result() waiting for the end_file event
  2. Event thread blocks on mpv_wait_event(handle, -1)
  3. Cocoa needs the main thread to process events → but it's blocked
  4. No events are ever delivered → deadlock

Fix

Replace the blocking event loop with a pipe-based wakeup mechanism:

  • Create a self-pipe for wakeup signaling
  • Register mpv_set_wakeup_callback to write to the pipe when events arrive
  • Use select.select() on the pipe fd with 100ms timeout instead of blocking forever
  • Drain events with mpv_wait_event(handle, 0) (non-blocking) after each wakeup
  • Clean up pipe and unregister callback in finally block

Testing

  • python3 -m py_compile mpv.py passes
  • The focused unit test from PR Fix race in event wait setup #312 (race condition fix) is a separate issue
  • This fix addresses the macOS-specific threading deadlock

Closes #61

Replace blocking mpv_wait_event(handle, -1) with a pipe-based wakeup
mechanism to prevent deadlocks on macOS where Cocoa requires the main
thread for its event loop.

- Create a self-pipe for wakeup signaling
- Register mpv_set_wakeup_callback to write to the pipe when events arrive
- Use select.select() on the pipe fd with 100ms timeout instead of
  blocking forever on mpv_wait_event
- Drain events with mpv_wait_event(handle, 0) (non-blocking) after
  each wakeup or timeout
- Clean up pipe and unregister callback in finally block

This resolves the deadlock where wait_for_playback() would hang forever
on macOS because:
1. Main thread blocks on result.result() waiting for end_file event
2. Event thread blocks on mpv_wait_event(handle, -1)
3. Cocoa needs the main thread to process events, but it's blocked
4. No events are ever delivered → deadlock

Closes jaseg#61
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stuck in threading on macOS

2 participants