getsentry / getsentry/sentry-react-native
Session Replay resumes capture on didBecomeActive with no delay, causing fatal iOS App Hangs (watchdog kill)
- 主要言語
- TypeScript
- スター
- 1.8k
- フォーク
- 366
- 平均マージ
- 1日 5時間
- マージ済み PR(30日)
- 93
説明
### What React Native libraries do you use?
React Native without Frameworks
### Are you using sentry.io or on-premise?
sentry.io (SaS)
### Are you using any other error monitoring solution alongside Sentry?
No
### Other Error Monitoring Solution Name
_No response_
### @sentry/react-native SDK Version
8.8.0
### How does your development environment look like?
````
⬇ Place the `npx react-native@latest info` output here. ⬇
System:
OS: macOS 26.5.1
CPU: (10) arm64 Apple M5
Memory: 253.89 MB / 24.00 GB
Binaries:
Node: 26.0.0
Yarn: 1.22.22
npm: 11.18.0
Watchman: Not Found
IDEs:
Xcode: 26.6/17F113
Languages:
Java: 21.0.11
Ruby: 3.3.6
npmPackages:
"@react-native-community/cli": 20.1.2
react: 19.1.0
react-native: 0.81.1
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: true
````
### Sentry.init()
````js
Sentry.init({
dsn: sentryDsn,
enabled: true,
environment: __DEV__ ? 'development' : 'production',
sendDefaultPii: false,
tracesSampleRate: 0.2,
profilesSampleRate: 0.1,
enableLogs: true,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
integrations: [
navigationIntegration,
Sentry.mobileReplayIntegration({
maskAllText: false,
maskAllImages: false,
maskAllVectors: false,
// Skip video / AVKit view trees during Session Replay screenshotting.
// Traversing RCTVideo (and AVPlayer fullscreen presentation layers) can
// fatal with -[NSConcreteValue doubleValue] while CA animations run.
// See: getsentry/sentry-react-native#5548, getsentry/sentry-cocoa#7810
excludedViewClasses: [
'RCTVideo',
'AVPlayer',
'AVPlayback',
'AVNowPlaying',
'AVFullScreen',
'AVKit',
],
}),
],
````
### Steps to Reproduce
# Session Replay resumes capture on didBecomeActive with no delay, causing fatal iOS App Hangs (watchdog kill)
## Description
On iOS, Session Replay's screenshot pass is resumed synchronously on
`UIApplication.didBecomeActiveNotification`. Because the capture walks the view
hierarchy and re-renders the window on the main thread, and because iOS applies
its strictest watchdog to foreground transitions, a heavy view tree at resume
can block the main thread past 2s and the app is terminated.
We are seeing this in production as `Fatal App Hang Fully Blocked`, with
`SentrySessionReplay.takeScreenshot` as the symbolicated culprit.
The relevant code is `SentrySessionReplayIntegration.swift`, which wires resume
straight to the notification:
```swift
notificationCenter.addObserver(self, selector: #selector(pause),
name: UIApplication.didEnterBackgroundNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(resume),
name: UIApplication.didBecomeActiveNotification, object: nil)
```
There is no configurable delay or jitter before the first capture after resume,
and no way to defer it from JS: `SentryReplayApi` exposes `pause`/`resume`/
`start`/`stop` natively, but the React Native bridge only forwards
`captureReplay` and `getCurrentReplayId` (`NativeRNSentry.d.ts`), so a React
Native app cannot pause replay across the foreground transition even as a
workaround.
## Evidence
Two events from the same issue, on very different hardware, both with the
identical breadcrumb shape:
**iPhone XR, iOS 18.1.1**
```
10:17:20.609 app.lifecycle background
10:17:21.412 device.event Low memory LOW_MEMORY
... 2h 56m ...
13:13:52.441 app.lifecycle foreground
13:13:52.593 app.lifecycle active
13:13:53-54 app's own rehydration requests
13:13:55.628 Fatal App Hang Fully Blocked <- 3.2s after active
```
**iPhone 16 Pro, iOS 26.6.1**
```
04:40:37.783 app.lifecycle background
... ~4 min ...
04:44:34.536 app.lifecycle foreground
04:44:34.766 app.lifecycle active
04:44:34-35 app's own rehydration requests
04:44:36.970 Fatal App Hang Fully Blocked <- 2.4s after active
```
Points worth noting:
- Time spent in background is irrelevant (2h56m vs 4min); the trigger is the
resume itself.
- It reproduces on current hardware, not just older devices — an iPhone 16 Pro
on iOS 26 hit the same group as an iPhone XR on iOS 18.
- The JS thread is idle in both. This is entirely native.
- `enableViewRendererV2` is on (SDK default), so this is with the fast renderer
already in use.
## Steps to reproduce
1. Init with Session Replay in buffer mode (`replaysOnErrorSampleRate: 1.0`).
2. Open a screen with a large view tree (in our case a chat list backed by a
long message list).
3. Background the app.
4. Return to the foreground while the app also does meaningful work on the main
thread at resume (state rehydration, list re-render).
5. On a device under memory pressure this blocks past the watchdog threshold
and iOS terminates the app.
Reproduction is probabilistic rather than deterministic — it depends on how
much work lands in the same window. We have 4 events across 4 users.
## Expected result
Resuming replay after a foreground transition should not be able to terminate
the app. Some possibilities, in rough order of preference:
1. Defer the first capture after `didBecomeActive` by a short interval, or
schedule it off the watchdog-critical window.
2. Expose an option for that delay in `SentryReplayOptions` /
`MobileReplayOptions`.
3. Bridge `SentryReplayApi`'s `pause`/`resume` to React Native, so apps can at
least implement the workaround themselves.
## Actual result
The first capture runs immediately on `didBecomeActive`, on the main thread,
and the watchdog kills the app.
### Expected Result
No App hang
### Actual Result
App hangs after it comes to foreground state
コントリビューションガイド
評価
この issue はまだ評価されていません。