Skip to content

apple: fix crash when video_threaded is enabled with the Cocoa/Metal driver#19165

Draft
vanreece wants to merge 1 commit into
libretro:masterfrom
vanreece:pr-macos-threaded-video-crash
Draft

apple: fix crash when video_threaded is enabled with the Cocoa/Metal driver#19165
vanreece wants to merge 1 commit into
libretro:masterfrom
vanreece:pr-macos-threaded-video-crash

Conversation

@vanreece

@vanreece vanreece commented Jul 4, 2026

Copy link
Copy Markdown

Summary

Enabling video_threaded = true on macOS crashes RetroArch immediately with the
Cocoa/Metal driver.

The threaded-video worker thread runs graphics-driver init, which calls into the
Cocoa UI layer — -[CocoaView setViewType:] and -[CocoaView setVideoMode:]
and mutates NSWindow/NSView state off the main thread. AppKit forbids that,
so the process aborts ("NSWindow should only be modified on the main thread").

A plain dispatch_sync to the main queue is not enough on its own: during
CMD_INIT the main thread is parked in scond_wait() inside
video_thread_wait_reply(), so it never drains the main queue and the dispatch
would deadlock.

Fix

Two halves, both required:

  • gfx/video_thread_wrapper.c — for CMD_INIT on Apple platforms, wait by
    pumping the main run loop in short slices (CFRunLoopRunInMode, 2 ms) and
    polling for the reply, instead of scond_wait(). All other commands keep the
    original lightweight wait, so there is no change off the init path.
  • ui/drivers/ui_cocoa.m-[CocoaView setViewType:] and
    -[CocoaView setVideoMode:] bounce to the main thread when invoked off it;
    combined with the pump above, the dispatch_sync completes instead of
    deadlocking.

Testing

Built on macOS (Apple Silicon, Metal). Before: video_threaded=true +
video_driver=metal crashes on load. After: launches and runs normally. The
default video_threaded=false path is unchanged — new code is gated to
CMD_INIT on __APPLE__.

🤖 Generated with Claude Code

…driver

Enabling video_threaded on macOS crashes immediately. The threaded video
worker runs the graphics driver init, which reaches into the Cocoa UI
layer -- -[CocoaView setViewType:] and -[CocoaView setVideoMode:] -- and
mutates NSWindow/NSView state off the main thread. AppKit forbids that,
so the process aborts ("NSWindow should only be modified on the main
thread").

A plain dispatch_sync to the main queue is not enough on its own: during
CMD_INIT the main thread is parked in scond_wait() inside
video_thread_wait_reply(), so it never drains the main queue and the
dispatch would deadlock.

Fix both halves:
 - video_thread_wrapper.c: for CMD_INIT on Apple platforms, wait by
   pumping the main run loop in short slices (CFRunLoopRunInMode, 2 ms)
   and polling for the reply, instead of scond_wait(). This lets the
   worker's main-queue AppKit work execute during init. All other
   commands keep the original lightweight wait.
 - ui_cocoa.m: -[CocoaView setViewType:] and -[CocoaView setVideoMode:]
   bounce to the main thread when invoked off it; combined with the pump
   above, the dispatch_sync completes instead of deadlocking.

With both changes, video_threaded=true no longer crashes the Metal
driver on macOS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vanreece

vanreece commented Jul 4, 2026

Copy link
Copy Markdown
Author

Sorry if AI generated PRs aren't welcome. Feel free to hate on it, but I thought it might be useful.

@LibretroAdmin

Copy link
Copy Markdown
Contributor

If this actually works it would be a big deal - for a long time we had to simply 'stub out' threaded video because we couldn't figure out a way to make it work with Cocoa

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.

2 participants