Skip to content

Report Hermes fatal errors on the New Architecture - #59729

Draft
kraenhansen wants to merge 1 commit into
react:mainfrom
kraenhansen:fix/hermes-fatal-handler-new-arch
Draft

kraenhansen wants to merge 1 commit into
react:mainfrom
kraenhansen:fix/hermes-fatal-handler-new-arch

Conversation

@kraenhansen

Copy link
Copy Markdown
Contributor

Summary:

Fixes #59728.

hermesFatalHandler, which logs the reason for a Hermes fatal error and records it as the abort message, is only installed by HermesExecutorHolder on the legacy path. On the New Architecture nothing sets a handler, so Hermes writes the reason to stderr, which doesn't reach logcat, and crashes with its deliberate null write. The result is a SIGSEGV with no reason.

This installs the same handler from JHermesInstance::initHybrid, once per process. It's kept separate from the handler in reactexecutor/OnLoad.cpp so that the legacy code can be removed on its own.

Changelog:

[ANDROID] [FIXED] - Report the reason for Hermes fatal errors in logcat and tombstones on the New Architecture

Test Plan:

Used the reproducer from the issue, https://github.com/kraenhansen/rn-hermes-fatal-handler-repro, on an arm64 API 37 emulator. It's a stock 0.88.1 release app that exhausts a small-heap runtime after startup. The same change was applied to v0.88.1, ReactAndroid was built from source, and the resulting libhermestooling.so was swapped into the APK. The change itself wasn't built on main.

Before:

I HermesGC: OOM: [repro] reason = Max heap size was exceeded (...)
F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 7064 (Thread-2), pid 6925 (com.fatalrepro)
F DEBUG   : Cause: null pointer dereference

After, in 3 of 3 runs, with the app setting no handler:

I HermesGC: OOM: [repro] reason = Max heap size was exceeded (...)
F Hermes  : OOM: error_code(value = 1, category = vm_allocate_category, message = Max heap size was exceeded)
F libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 8464 (Thread-2), pid 8405 (com.fatalrepro)
F DEBUG   : Abort message: 'OOM: error_code(value = 1, category = vm_allocate_category, message = Max heap size was exceeded)'

Note that fatal errors now end in SIGABRT rather than SIGSEGV, matching the legacy path, which may change how they group in crash reporters. An app that sets its own handler before HermesInstance is created would be replaced, because Hermes has a single handler and no getter.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hermes fatal error reason is lost on the New Architecture: setFatalHandler is only called from the legacy executor

1 participant