Skip to content

feat(ios): Report JS thread hangs as errors (prototype) - #6964

Draft
alwx wants to merge 1 commit into
mainfrom
alwx/feature/3460
Draft

alwx wants to merge 1 commit into
mainfrom
alwx/feature/3460

Conversation

@alwx

@alwx alwx commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • New feature

📜 Description

This draft is a prototype for iOS on the New Architecture. A native watchdog thread schedules an empty task on the JS thread through the React Native CallInvoker. If the task does not run within jsHangTimeoutInterval (2 s by default), the SDK samples the JS thread with the Hermes sampling profiler and captures an error event with the JS stack.

💡 Motivation and Context

An infinite loop in JS blocks the JS thread but not the UI thread, so the native App Hang tracker sends nothing. JS stall tracking cannot report it either, because no JS code runs while the thread is blocked. Closes #3460.

💚 How did you test it?

I ran the sample app on the iOS 26.1 simulator (Debug, New Architecture, static frameworks). The "Block JS thread for 5s" and "Block JS thread forever" buttons each produced one event, and the top JS frame was the function that blocked the thread. The event was sent while JS was still blocked. yarn lint, the SDK tests, circularDepCheck, and the API report pass. One tools test (sentryMetroSerializer) also fails on main.

📝 Checklist

  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • No breaking changes.

🔮 Next steps

Before this is ready, it needs Android support, a Release build test with source-map symbolication, and a start path for apps that start the native SDK with RNSentrySDK start. It also needs coordination with Hermes profiling, unit tests, and a CHANGELOG entry.

A blocked JS thread is not seen by the native App Hang tracker, because the UI thread stays free. JS stall tracking cannot report it either, because no JS code runs while the thread is blocked. An infinite loop in JS therefore produced no event.

RNSentryJSHangTracker runs on its own native thread. Every 100 ms it schedules an empty task on the JS thread through the React Native CallInvoker. When the task does not run within jsHangTimeoutInterval (2 s by default), it samples the JS thread with the Hermes sampling profiler for 300 ms and captures an error event with the last JS stack. The tracker waits for the first answer from the JS thread before it measures, so loading the bundle is not reported as a hang.

RNSentry is loaded through the interop layer, so getTurboModule is never called. The tracker gets the CallInvoker from setCallInvoker:, which React Native calls on modules that implement it. SentrySDKWrapper gets captureEvent:, because Objective-C++ cannot call the Swift SentrySDK class.

The options are internal and opt-in. The sample app enables them and adds two buttons that block the JS thread.
@github-actions

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

⚪ None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • feat(ios): Report JS thread hangs as errors (prototype) by alwx in #6964

🤖 This preview updates automatically when you update the PR.

@github-actions

Copy link
Copy Markdown
Contributor
Fails
🚫 Pull request is not ready for merge, please add the "ready-to-merge" label to the pull request
🚫 Please consider adding a changelog entry for the next release.
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Features

- Report JS thread hangs as errors (prototype) ([#6964](https://github.com/getsentry/sentry-react-native/pull/6964))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against 0f9e51b

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Report JS Loop stalls as Errors (similar to App Hangs on iOS)

1 participant