Repository navigation
renderer: only start and stop the CVDisplayLink on the main thread - #14691
Merged
Merged
Conversation
Fixes #14150 The render thread started and stopped its CVDisplayLink directly. Turns out this is NOT SAFE TO DO! I actually couldn't find any docs or anything to point this out to me and I had to rely on Fable-assistance disassembling CoreVideo frameworks to confirm the behavior. I read the disassembly myself and can confirm the reading matches what I'd see. CoreVideo performs the very same stop and start on the main thread inside its display reconfiguration callback, which fires on display sleep and wake, resolution changes, etc. CVDisplayLinkStop clears the link's running flag and then waits, once and unconditionally, for the IO thread to notice and exit. The link's mutex is released during that wait. If CVDisplayLinkStart lands in that window, the flag is set again and a second IO thread is created. The first IO thread wakes, sees the flag set, and keeps looping, so the waiting stop is never signaled. Whichever side lost was stuck in CVDisplayLinkStop forever. In the reports that was sometimes our render thread and sometimes CoreVideo's own call on the main thread. Either way the main thread eventually waited on the renderer (focus change, tab close, quit) and the whole app froze with no "Not Responding" indication. The spindumps all show one CVDisplayLink object with two live IO threads, which is exactly this problem.
|
Thank you for fixing @mitchellh |
This was referenced Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #14150
The render thread started and stopped its CVDisplayLink directly. Turns out this is NOT SAFE TO DO!
I actually couldn't find any docs or anything to point this out to me and I had to rely on Fable-assistance disassembling CoreVideo frameworks to confirm the behavior. I read the disassembly myself and can confirm the reading matches what I'd see.
CoreVideo performs the very same stop and start on the main thread inside its display reconfiguration callback, which fires on display sleep and wake, resolution changes, etc.
CVDisplayLinkStop clears the link's running flag and then waits, once and unconditionally, for the IO thread to notice and exit. The link's mutex is released during that wait. If CVDisplayLinkStart lands in that window, the flag is set again and a second IO thread is created. The first IO thread wakes, sees the flag set, and keeps looping, so the waiting stop is never signaled. Whichever side lost was stuck in CVDisplayLinkStop forever.
In the reports that was sometimes our render thread and sometimes CoreVideo's own call on the main thread. Either way the main thread eventually waited on the renderer (focus change, tab close, quit) and the whole app froze with no "Not Responding" indication. The spindumps all show one CVDisplayLink object with two live IO threads, which is exactly this problem.