Skip to content

AetherEngine 5.19.1

Choose a tag to compare

@superuser404notfound superuser404notfound released this 22 Jul 17:28

Patch release: recovery for a VOD producer that dies mid-session at the tail (#169, round 2).

Fixed

A VOD session whose producer dies mid-session now recovers instead of parking into -12889 (1ba1b8c)

Reported by @rrgomes with a decisive trace (4K HEVC DV P8.1 MKV, direct play over LAN, Apple TV 4K): near the end of the file the source reader stopped for good after reconnect churn, the final segment (seg719) was never produced, and the request for it re-armed a 30 s backpressure wait indefinitely (cache miss after 30005ms (cache=46 restarted=false) x11) until AVPlayer collapsed with CoreMediaErrorDomain -12889.

Three defects lined up:

  1. A mid-session VOD readError pump exit had no recovery arm at all. Only the nothing-ever-produced case surfaced as fatal (#126); the rest was assumed covered by the scrub/wedge arms, but the backpressure wedge detector runs inside the pump and died with it.
  2. The forward-wait branch judged "will this arrive?" by index distance to the producer's march front alone (the mechanism the reporter identified, confirmed verbatim). A dead producer freezes the front just below the request, so the wait re-armed forever. The final segment is maximally exposed: there is nothing beyond it for the march to advance into.
  3. Even an escalated restart would have been vetoed: the restart loop's producerCovers guard reads the dead producer's still-installed base, which covers the requested index.

Three-layer fix, defense in depth (VOD only; live keeps its pump watchdogs and reopen machinery):

  • Event-driven revive: a mid-session readError exit gets a bounded revive (2 attempts) aimed at the pending seek target or AVPlayer's real position, and the demuxer whose read just threw is replaced with a fresh connection via the existing #79 path instead of being re-seeked.
  • Liveness-aware forward wait: a FINISHED pump skips the backpressure wait entirely and restarts immediately; a pump that never exits (blocked in a read) escalates once a full wait burned with zero march-front progress for the same index. An advancing front resets the record, preserving the #141/#93 patience for slow-but-alive sources.
  • producerCovers bypass: both proofs override the veto so the escalated restart actually fires.

Retest log signatures: #169 VOD pump died mid-session (readError N); rebuilding producer on a fresh demuxer at ... (pump-exit path) or seg719: #169 forward-wait march dead (front=718 frozen across a full wait); escalating to restart (silent-stop path).

Covered by Issue169DeadProducerEscalationTests (7 tests). Full suite 965/965 green; strict-concurrency and tvOS Simulator builds clean.

Thanks to @rrgomes for removing their host mitigation to isolate the engine behavior, for the memprobe evidence that the producer was provably stopped, and for the exact code-level mechanism in VideoSegmentProvider, which this release confirms and fixes.