getsentry / getsentry/sentry-react-native

Session Replay resumes capture on didBecomeActive with no delay, causing fatal iOS App Hangs (watchdog kill)

Offen
#6,701 2 Kommentare 0 Reaktionen 1 zugewiesene Person Beansprucht von @alwx Auf GitHub ansehen
Bug React-Native Replays
Vorherrschende Sprache
TypeScript
Sterne
1.8k
Forks
366
Ø Merge
1 T. 9 Std.
Gemergte PRs (30 T.)
89

Beschreibung

### 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

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.