Skip to content

fix: crash-time hang reading scene window - #9282

Merged
itaybre merged 1 commit into
mainfrom
fix/crash-screenshot-mainactor-scene-delegate
Oct 6, 2026
Merged

itaybre merged 1 commit into
mainfrom
fix/crash-screenshot-mainactor-scene-delegate

Conversation

@antonis

@antonis antonis commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

📜 Description

During a crash, the SDK collects the app's windows so it can attach a screenshot or view hierarchy. It did this by reading the scene delegate's window property. If that delegate is written in Swift (such as Expo SDK 57's ExpoAppSceneDelegate), the window getter is @MainActor-isolated, so reading it off the main thread trips Swift's isolation check and traps. Because this runs inside the crash handler, the trap re-enters the signal path and freezes the app for non-Mach crashes like std::terminate or abort.

On the crash thread the SDK now reads UIWindowScene.windows directly, a plain UIKit property with no isolation check, so the Swift getter is never called from the crash thread. The main-thread path keeps reading the scene delegate's window as before, so only crash-time screenshot and view hierarchy capture change.

Alternative considered

The initial fix read UIWindowScene.windows on every path, but that would have changed long-stable window selection for non-crash consumers (session replay, app-hang, view hierarchy); scoping the change to the crash thread keeps their behavior identical and limits the change to where reading the delegate is impossible anyway.

💡 Motivation and Context

Fixes #9281

The regression shipped in 9.29.0 via the crash-time screenshot feature (#8986), which first called this window-collection code on the crash thread; it was previously only ever invoked on the main thread.

Impact

Latest Expo 57 (≈57.0.23+) apps that are on the UIScene lifecycle, with screenshots enabled, built for iOS 26/27.

💚 How did you test it?

📝 Checklist

You have to check all boxes before merging:

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • If I added a new public API, I also added it to the SentryObjC wrapper.

@antonis antonis added the run-full-ci Allows gated GitHub Action workflows to run for a labelled pull request label Oct 5, 2026

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

@sentry

sentry Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Size Analysis

1 component analyzed

iOS Builds

Name Configuration Version Download Size Install Size
SDK-Size (iOS)
io.sentry.sample.SDK-Size
Release 9.30.0 (1) 1.2 MB (+899 B) 3.2 MB (0 B)

Configure sentry-cocoa status check rules

@sentry

sentry Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

📲 Install Builds

iOS

🔗 App Name App ID Version Configuration
SDK-Size io.sentry.sample.SDK-Size 9.30.0 (1) Release

⚙️ sentry-cocoa Build Distribution Settings

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1218.15 ms 1265.28 ms 47.13 ms
Size 24.14 KiB 1.37 MiB 1.34 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
c5a3e1c 1226.65 ms 1263.67 ms 37.02 ms
ec88236 1219.04 ms 1253.69 ms 34.65 ms
cd4994f 1220.89 ms 1252.61 ms 31.72 ms
810485b 1212.58 ms 1252.45 ms 39.87 ms
a29e132 1225.98 ms 1258.31 ms 32.34 ms
5a9c804 1220.29 ms 1255.17 ms 34.88 ms
3b55bda 1224.45 ms 1261.31 ms 36.86 ms
047965c 1219.57 ms 1252.02 ms 32.45 ms
22550bf 1223.24 ms 1259.38 ms 36.14 ms
2c9ee54 1226.87 ms 1251.10 ms 24.23 ms

App size

Revision Plain With Sentry Diff
c5a3e1c 24.14 KiB 1.23 MiB 1.20 MiB
ec88236 24.14 KiB 1.15 MiB 1.13 MiB
cd4994f 24.14 KiB 1.17 MiB 1.14 MiB
810485b 24.14 KiB 1.24 MiB 1.22 MiB
a29e132 24.14 KiB 1.18 MiB 1.15 MiB
5a9c804 24.14 KiB 1.15 MiB 1.13 MiB
3b55bda 24.14 KiB 1.22 MiB 1.20 MiB
047965c 24.14 KiB 1.22 MiB 1.20 MiB
22550bf 24.14 KiB 1.23 MiB 1.20 MiB
2c9ee54 24.14 KiB 1.17 MiB 1.15 MiB

Previous results on branch: fix/crash-screenshot-mainactor-scene-delegate

Startup times

Revision Plain With Sentry Diff
3b0254b 1221.65 ms 1255.24 ms 33.59 ms

App size

Revision Plain With Sentry Diff
3b0254b 24.14 KiB 1.36 MiB 1.34 MiB

collectWindowsOnCurrentThread() runs on the KSCrash handler thread
and read the scene delegate's `window`. A Swift UIWindowSceneDelegate
has a @MainActor-isolated `window` getter, so reading it off the main
thread trips Swift's runtime isolation enforcement and traps with
SIGTRAP inside the signal handler, hanging the process on non-Mach
crashes (std::terminate, abort).

Read UIWindowScene.windows on the crash thread instead, which is a
plain UIKit property with no isolation check. The main-thread path
(internal_getWindows) keeps reading the delegate's window, so only
crash-time screenshot and view hierarchy capture change.

Fixes #9281
@antonis
antonis force-pushed the fix/crash-screenshot-mainactor-scene-delegate branch from f6d0ca7 to ebb6514 Compare October 5, 2026 11:31

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ebb6514. Configure here.

@antonis
antonis marked this pull request as ready for review October 5, 2026 12:01

@itaybre itaybre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, ran and reproduced the issue with your testing case.
Proof with crash including a snapshot too: https://sentry-sdks.sentry.io/issues/7776321012/?project=5428561&query=is%3Aunresolved&referrer=issue-stream

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

Labels

approved run-full-ci Allows gated GitHub Action workflows to run for a labelled pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants