Skip to content

iOS: backgrounding the app is reported as a JS long task lasting the entire background duration #1523

Open

Description

@jmaixl

Describe the bug

On iOS, when the app goes to the background and comes back, the SDK reports one JS long task (long_task.target: javascript) whose duration equals the whole time the app was in the background. This was tested and confirmed via iPhone 16e simulator and analyzing the code. There seems to be no attributes to discern backgrounded apps on iOS.

The root cause may be that the display link is never paused or the timestamp is never reset when the host is paused and resumed. React Native on Android and native iOS do this.

Reproduction steps

Run the app on iOS with RUM enabled and any non-zero longTaskThresholdMs. Background the app, wait, bring the app back. In RUM Explorer, search for the app and confirm there is a long task for this backgrounded duration.

SDK logs

No response

Expected behavior

Time spent in the background is never reported as a JS long task. The first frame after the app returns to the foreground should start a new measurement, as it does on Android

Affected SDK versions

3.8.0

Latest working SDK version

N/A

Did you confirm if the latest SDK version fixes the bug?

Yes

Integration Methods

NPM

React Native Version

0.86.3

Package.json Contents

▎ "react-native": "0.86.3",
▎ "expo": "57.0.24",
▎ "@datadog/mobile-react-native": "3.8.0",
▎ "@datadog/mobile-react-native-session-replay": "3.8.0",
▎ "@datadog/mobile-react-native-babel-plugin": "3.8.0",
▎ "expo-datadog": "57.0.0"

iOS Setup

Expo prebuild

Android Setup

No response

Device Information

iOS 26.2 on iPhone 16e Simulator (iPhone17,5).

Other relevant information

No response

Activity

  1. pcbeingused333 commented on Oct 31, 2026

    @pcbeingused333

    Thanks for the detailed report. Looking at packages/core/ios/Sources/JSRefreshRateListener.swift, there are two problems that together match what you see. First, JSRefreshRateMonitor.appWillResignActive() / appDidBecomeActive() (lines 33-39) are not called from anywhere in packages/core/ios, so the CADisplayLink is never stopped when the app goes to the background. Second, even if they were called, JSRefreshRateListener never resets lastFrameTimestamp (line 56), so the first onFrameTick after resuming computes frameTimestamp - lastFrameTimestamp across the whole time spent in the background, and frameTimeCallback reports it as a long task.

    A minimal fix would be to reset lastFrameTimestamp = -1 in start() (inside the jsQueue.async block), and to register UIApplication.willResignActiveNotification / didBecomeActiveNotification observers in JSRefreshRateMonitor that call the existing two methods. That way the first frame after returning to the foreground only starts a new measurement, as on Android.

    I'd be happy to open a PR with this plus an XCTest for the reset. I can't build the iOS target in my environment, so if you'd prefer a fix verified on a Mac, I'm glad to leave it to you or to adapt the patch to your review.

    Disclosure: this comment was drafted with the help of an AI assistant (Claude).

  2. jmaixl commented on Nov 2, 2026

    @jmaixl
    Author

    Thanks. Looks like someone is working on it already. #1530

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions