Skip to content

Crash-time screenshot traps inside the crash handler under UIScene with a Swift (MainActor) scene delegate — app freezes after terminate/abort crashes #9281

Closed

Description

@pavelhamrik

Crash-time screenshot traps inside the crash handler under UIScene with a Swift (MainActor) scene delegate — app freezes after terminate/abort crashes

Platform / versions

sentry-cocoa 9.30.0 (via @sentry/react-native 8.29.0, prebuilt xcframework), iOS 27.0 (24A435), iPhone 16 Pro Max, Xcode 27.0 Release build. App uses the UIScene lifecycle; the scene delegate is Expo's ExpoAppSceneDelegate (Swift, open var window: UIWindow? on a UIWindowSceneDelegate, hence MainActor-isolated).

What happens

With attachScreenshot: true, an unhandled C++ exception (throw std::runtime_error on a detached thread → std::terminate) produces the expected cpp_exception event plus two more events and a frozen process:

  1. C++ Exception: St13runtime_error … — mechanism cpp_exception ✔
  2. _dispatch_assert_queue_fail — EXC_BREAKPOINT, mechanism mach, 2 s later
  3. _dispatch_assert_queue_fail — SIGTRAP, mechanism signal, 2 s after that

Then the app stays alive but unresponsive until the user swipes it away. All three arrive on the next launch.

Stack of events 2/3 (symbolicated from the device event):

__cxa_throw → __cxxabiv1::failed_throw → std::__terminate
  → [SentryCrash terminate handler → onCrash → SentryScreenshotIntegration closure
     → SentryScreenshotSource.saveScreenShots → SentryApplication.collectWindowsOnCurrentThread()
     → @objc ExpoAppSceneDelegate.window.getter]
  → swift_task_isCurrentExecutorWithFlagsImpl → _swift_task_checkIsolatedSwift
  → dispatch_assert_queue → _dispatch_assert_queue_fail

The same chain, with the bracketed frames named, was sampled on a Debug simulator build (sample of the hung process): SentryCrash Exception Handler (Primary) sits in handleExceptions → sentrycrashcm_handleException → onCrash → closure #1 in SentryScreenshotIntegration.init → SentryScreenshotSource.saveScreenShots → SentryApplication.collectWindowsOnCurrentThread() → @objc ExpoAppSceneDelegate.window.getter → _checkExpectedExecutor → dispatch_assert_queue → _dispatch_assert_queue_fail → _sigtramp → handleSignal → sentrycrashcm_handleException → onCrash → (same again), every other thread suspended, main thread parked mid-CoreAnimation commit.

Why

collectWindowsOnCurrentThread() runs on the crash handler thread and reads (scene.delegate as? UIWindowSceneDelegate)?.window. When the delegate is Swift, that getter is MainActor-isolated, and Swift 6.x's runtime isolation enforcement (swift_task_isCurrentExecutor → dispatch_assert_queue(main)) traps off the main queue — in Release too (only the _checkExpectedExecutor wrapper is Debug-only). The trap re-enters the signal path inside the handler. A Mach-exception crash still terminates (the secondary handler thread takes over); terminate/abort-class crashes never finish.

Expected

The crash-time capture should not call into a (possibly Swift, MainActor) scene delegate from the crash thread — e.g. read UIWindowScene.windows / keyWindow on the scene itself, or skip the capture when the delegate's getter cannot be called safely.

Workaround

attachScreenshot: false. The report itself is written before the screenshot step, so only the screenshot is lost.

Repro

Any UIScene app with a Swift UIWindowSceneDelegate whose window is a Swift property (Expo SDK 57's ExpoAppSceneDelegate is one), attachScreenshot: true, and a crash that is not a Mach exception — e.g. std::terminate from an uncaught C++ exception on a detached thread, or abort().

Activity

  1. linear-code commented on Oct 4, 2026

    @linear-code
  2. jpsim commented on Oct 5, 2026

    @jpsim

    We're hitting this on 9.30.0 with a Swift UIWindowSceneDelegate, and for mach crashes it's worse than losing the screenshot. The trap recrashes on the handler thread, so writeRecrashReport nests the original report under recrash_report, and the converter only reads user, sentry_sdk_scope and system from the top level. That stripped tags, breadcrumbs and OS/device contexts from about 87% of our foreground mach crashes since 9.29.0.

  3. added a commit that references this issue on Oct 7, 2026
    4f3ef87
  4. github-actions commented on Oct 7, 2026

    @github-actions
    Contributor

    A PR closing this issue has just been released 🚀

    This issue was referenced by PR #9282, which was included in the 9.30.1 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions