Split out of #408. Observed by @rrgomes on macOS 26.6.2 during the retest, one sample, and worth recording because the engine reads the same property from the same place.
What was seen
While AVPlayer was parked in the consumer wedge of #421, an AVPlayerItem.currentTime() call made from the host's main actor did not return for 13.3 s, and the app was fully blocked for that time. It came back 30 ms after the re-engage watchdog fired. The same wedge on an Apple TV the same afternoon returned instantly. The reporting host no longer reads the player from the main actor during a stall.
Why this is ours as well
Two engine reads sit on the main actor and would join the same wait:
AetherEngine+Loading.swift:1206, the stage-1 nudge: self.reengageStalledConsumer(position: player.currentTime().seconds, ...). This one is the sharper case, because it runs precisely when the consumer is wedged, which is the state in which the call was measured not returning.
NativeAVPlayerHost.bufferedEnd, which reads item.currentTime() before walking loadedTimeRanges.
AetherEngine+Diagnostics.swift:59 already treats these as sync XPC reads and hops them off the main actor for the memory probe ("#134: currentTime()/loadedTimeRanges are sync XPC reads"), so the hazard is known in one place and unguarded in the others.
Related: #254 has the same shape on the software path (SoftwarePlaybackHost.seek runs the deadline-free Demuxer.seek on the main actor, field App Hangs).
What would settle it
One sample on one platform is not a measurement. The engine has renderedPositionMirror for exactly this reason (the producer reads AVPlayer's position off-main through it), so the fix is likely to be small; the part that needs evidence first is whether the block is reproducible on macOS under a wedge, and whether tvOS is genuinely exempt or merely was not caught. aetherctl can hold a wedge open on the loopback path, which is where to try it.
Split out of #408. Observed by @rrgomes on macOS 26.6.2 during the retest, one sample, and worth recording because the engine reads the same property from the same place.
What was seen
While AVPlayer was parked in the consumer wedge of #421, an
AVPlayerItem.currentTime()call made from the host's main actor did not return for 13.3 s, and the app was fully blocked for that time. It came back 30 ms after the re-engage watchdog fired. The same wedge on an Apple TV the same afternoon returned instantly. The reporting host no longer reads the player from the main actor during a stall.Why this is ours as well
Two engine reads sit on the main actor and would join the same wait:
AetherEngine+Loading.swift:1206, the stage-1 nudge:self.reengageStalledConsumer(position: player.currentTime().seconds, ...). This one is the sharper case, because it runs precisely when the consumer is wedged, which is the state in which the call was measured not returning.NativeAVPlayerHost.bufferedEnd, which readsitem.currentTime()before walkingloadedTimeRanges.AetherEngine+Diagnostics.swift:59already treats these as sync XPC reads and hops them off the main actor for the memory probe ("#134: currentTime()/loadedTimeRanges are sync XPC reads"), so the hazard is known in one place and unguarded in the others.Related: #254 has the same shape on the software path (
SoftwarePlaybackHost.seekruns the deadline-freeDemuxer.seekon the main actor, field App Hangs).What would settle it
One sample on one platform is not a measurement. The engine has
renderedPositionMirrorfor exactly this reason (the producer reads AVPlayer's position off-main through it), so the fix is likely to be small; the part that needs evidence first is whether the block is reproducible on macOS under a wedge, and whether tvOS is genuinely exempt or merely was not caught.aetherctlcan hold a wedge open on the loopback path, which is where to try it.