Skip to content

macOS: AVPlayerItem.currentTime() from the main actor did not return for 13.3 s during a consumer wedge, and the engine reads it there in two places #422

Description

@superuser404notfound

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions