fix(apple): relink stage-4 when the display link stops vending #442

Merged
enricobuehler merged 1 commits from worktree-stage4-link-watchdog into main 2026-08-29 08:48:28 +00:00
1 Commits
Author SHA1 Message Date
enricobuehler 87bc0883db fix(apple): relink stage-4 when the display link stops vending
ci / bun-nix (pull_request) Successful in 32s
ci / docs-site (pull_request) Successful in 58s
ci / web (pull_request) Successful in 1m3s
ci / docs-drift (pull_request) Successful in 1m11s
apple / swift (pull_request) Successful in 2m10s
apple / distribute (pull_request) Skipped
apple / screenshots (pull_request) Skipped
ci / rust-arm64 (pull_request) Successful in 2m41s
ci / rust (pull_request) Successful in 22m48s
Field 2026-08-28, iPad Pro on iOS 27: the picture froze twice in one
session while audio and input kept running, and only reconnecting
cleared it. pf-present logged decode at full rate against ok=0,
noDrawable=120 and no vendLeadMs samples at all, so the
CAMetalDisplayLink had stopped calling back.

Stage-4 has no drawable source of its own: every drawable arrives as
update.drawable. A link that goes quiet is therefore a stream that
never presents again, and nothing noticed. Stage-3's
PresentGate.staleAfter insurance does not reach this path, and the
link is only invalidated at session teardown.

The render thread now tracks how long it has gone without a vend and,
past 250 ms with frames still decoding, retires the link generation
and starts a fresh one. Invalidating the old link also returns the
drawables it holds, so this covers an exhausted pool as well as a
dead link. The relink is logged to the send-logs ring.

Also holds the link delegate for the link thread's lifetime. It is
stored weakly and was kept alive only by a local whose last use is
that store, which ARC is free to release on the spot.
2026-08-29 09:54:39 +02:00