Skip to content

renderer: never stop the display link while holding the draw mutex - #14171

Merged
mitchellh merged 1 commit into
mainfrom
displaysync
Sep 7, 2026
Merged

mitchellh merged 1 commit into
mainfrom
displaysync

Conversation

@mitchellh

Copy link
Copy Markdown
Contributor

Fixes #14150

drawFrame called syncDisplayLink from its no-redraw path while still holding draw_mutex, and syncDisplayLink stops the CVDisplayLink when there is no work left. CVDisplayLinkStop is a blocking join on CoreVideo's IO thread. On macOS the apprt also calls drawFrame from the CoreAnimation layer display callback on the main thread, which takes the same mutex, so any CoreVideo stall inside that stop deadlocked.

Fixes #14150

drawFrame called syncDisplayLink from its no-redraw path while still
holding draw_mutex, and syncDisplayLink stops the CVDisplayLink when
there is no work left. CVDisplayLinkStop is a blocking join on
CoreVideo's IO thread. On macOS the apprt also calls drawFrame from the
CoreAnimation layer display callback on the main thread, which takes
the same mutex, so any CoreVideo stall inside that stop deadlocked.
@mitchellh
mitchellh requested a review from a team as a code owner September 7, 2026 16:22
@ghostty-bot ghostty-bot Bot added the renderer label Sep 7, 2026
@mitchellh
mitchellh merged commit 82232ec into main Sep 7, 2026
204 checks passed
@mitchellh
mitchellh deleted the displaysync branch September 7, 2026 16:45
@github-actions github-actions Bot added this to the 1.4.0 milestone Sep 7, 2026
danielitus added a commit to danielitus/ghostty that referenced this pull request Sep 25, 2026
…e deadlock

The fork kept the CVDisplayLink running whenever the surface was visible
and guarded every stop() with isRunning(), to make CVDisplayLinkStop as
rare as possible after the 2026-09-04 freeze (render thread stuck inside
it, mailbox full, app thread blocked in occlusionCallback).

Upstream 72cf508 (ghostty-org#14171, fixes ghostty-org#14150) removes the
only explained cause of that stall: drawFrame no longer calls
syncDisplayLink while holding draw_mutex, so a stop can no longer
deadlock against the main thread's layer-display draw. Restore upstream's
idle parking of the link (stopped when there are no cell changes or
animation) and its unguarded stop calls; stopping a link that is not
running returns immediately without joining anything.

The containment layer (bounded mailbox pushes, deferred-state recovery,
bounded teardown) is unchanged and still covers a render thread that
stalls for any other reason.
danielitus added a commit to danielitus/ghostty that referenced this pull request Sep 26, 2026
…fixes the deadlock"

This reverts commit 9b1da26.

The removal assumed upstream ghostty-org#14171 (72cf508) closed the
CVDisplayLinkStop deadlock. It only closes the draw_mutex variant.
Follow-ups on ghostty-org#14150 (2026-09-09 through 09-25) and
the open ghostty-org#14361 (2026-09-23) show the stall still happening on builds
that include it: the render thread wedges inside CoreVideo during a
display reconfiguration, and the app then freezes on the next
unbounded mailbox push from the main thread or when surface teardown
joins the thread. One reporter suspects the per-frame start/stop churn
from ghostty-org#14035 widens the window.

Keep the link running while visible and stop it only on occlusion, as
before, until upstream lands a fix that takes CVDisplayLinkStop off the
render and main threads entirely.
@cattyhouse

Copy link
Copy Markdown

hi @mitchellh , the problem as not full fixed by this PR, see my update #14150 (comment)

@pluiedev

Copy link
Copy Markdown
Member

@cattyhouse Please do not ping maintainers or comment on old pull requests. Open a discussion instead.

@ghostty-org ghostty-org locked and limited conversation to collaborators Sep 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants