Skip to content

iOS 26: rebuild()/root-tree mutation while a system modal (StoreKit sheet / ASWebAuthenticationSession) is presented crashes or leaves the window detached (white, frozen) #5203

@proggeramlug

Description

@proggeramlug

Perry version: 0.5.1161 (iOS, device on iOS 26.x)

Summary

Mutating the widget tree (calling the app's rebuild() that clears+rebuilds the root container) while a system modal is presented — StoreKit's purchase sheet (Product.purchase()) or GoogleSignIn's ASWebAuthenticationSession — either segfaults or leaves the app's root window detached (white, frozen, even subsequent rebuilds don't recover) on iOS 26.

This is the same hazard class the button path already documents/avoids for touch processing:

// crates/perry-ui-ios/src/widgets/button.rs
// "Dispatch async to avoid modifying the view hierarchy during UIKit touch
//  event processing (crashes on iOS 26+)."

…but it also applies to presented modals, not just touch dispatch.

Repro (in-app)

  1. Tap a button whose handler sets some state and calls triggerRebuild(), then awaits a StoreKit purchase or GoogleSignIn flow (which presents a system sheet). The scheduled rebuild fires (via the heartbeat) while the sheet is up.
  2. Result: SIGSEGV (StoreKit sheet) or a white/frozen window after the sheet dismisses (ASWebAuthenticationSession). The process stays alive in the white case; the Perry window/root view is detached and no rebuild restores it.

We hit this three times (purchase → SIGSEGV; restore + Google-link → white/frozen). Workaround: do not rebuild between initiating the flow and awaiting it (only rebuild after the sheet dismisses).

Ask

Either document this hazard in the perry/ui guidance, or make rebuild()/root-container mutation resilient to running while a modal is presented (e.g., defer root replacement until no presentedViewController, or re-make-key-and-visible after a presented controller dismisses). The "white + frozen, unrecoverable by rebuild" case (after ASWebAuthenticationSession) is the most serious — the root window never comes back.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions