fix: guard render encodes with the stall watchdog and serialize them on Android#177
Merged
Conversation
…on Android Follow-up hardening for the process-wide export gate: the gate serialized split and render encodes on iOS/macOS but left gaps that could re-introduce the deadlock it set out to fix. iOS/macOS: - Render encodes are now guarded by a shared ExportWatchdog (extracted from the split path), so a wedged render is force-cancelled and releases its gate slot instead of holding it forever and deadlocking every later export. - The watchdog uses a monotonic clock (immune to system-clock steps) and *relaxes* rather than disables the stall bound during the progress-silent container finalize, so a healthy moov rewrite is not misread as a stall while a wedged finalize still terminates. - BitrateCappedExporter completes its continuation on cancel (via a resume-once terminator + writer teardown), so a writer pump parked on a wedged encoder can no longer hang the body and leak the gate. Android: - Split and render now share a process-wide ExportGate (parity with iOS/macOS); a split queued behind a running render waits for the encoder instead of the stall watchdog failing it fast. - Render gained a stall watchdog with an adaptive bound that tolerates slow long renders (Media3 reports whole-percent progress) while still catching a stuck-at-0 wedge and releasing the gate. - A synchronous Transformer.start() failure and the failure-path duration probe no longer leak the gate or block the main thread; the cancel/stall terminals clean up the pre-rendered audio temps. Dart: SplitVideoModel asserts stallTimeout < exportTimeout. Tests: ExportGate JVM unit test, a watchdog failure-path integration test, and a Dart assertion test.
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.
Context
Follow-up hardening for the process-wide export gate added in #176. That change serialized split and render re-encodes on iOS/macOS so they stop starving each other on the hardware encoder, and added a stall/timeout watchdog to the split. A review of the merged code surfaced gaps where the gate could re-introduce the very deadlock it was meant to fix, plus a missing-parity gap on Android. This PR closes them.
Since
2.6.0was never published, these fixes fold into the2.6.0changelog rather than a new version.What changed
iOS / macOS
ExportWatchdog(extracted from the split path). Previously the render held a gate slot but had no watchdog, so a wedged VideoToolbox session held the single slot forever and deadlocked every later split/render. A wedged render is now force-cancelled and releases its slot.BitrateCappedExportercompletes its continuation on cancel (resume-once terminator + writer teardown), so a writer pump parked on a wedged encoder can no longer hang the body and leak the gate.Android
ExportGate(parity with iOS/macOS). A split queued behind a running render now waits for the encoder instead of the stall watchdog failing it fast.Transformer.start()failure and the failure-path duration probe no longer leak the gate or block the main thread; the cancel/stall terminals also clean up the pre-rendered audio temp files.Dart
SplitVideoModelnow assertsstallTimeout < exportTimeout(otherwise the hard bound pre-empts stall detection).Tests
ExportGateTest.kt— JVM unit test for the gate primitive (FIFO hand-off, single/idempotent release, no slot leak).stallTimeout < exportTimeout.Verification
ExportGateTest,SplitExportDiagnosticsTest).dart analyzeanddart formatclean.swiftc -parse.