Skip to content

C++ STL Library on Android does not support exception_ptr #48027

Closed

Description

@mrousavy

Description

For some reason, std::exception_ptr is broken in react-native.

I have added this code to react-native/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp:

__android_log_print(ANDROID_LOG_ERROR, "EXCEPTION", "Running exception test...");
try {
  throw std::runtime_error("Test exception");
} catch (...) {
  auto eptr = std::current_exception();
  try {
    std::rethrow_exception(eptr);
  } catch (const std::exception& e) {
    __android_log_print(ANDROID_LOG_ERROR, "EXCEPTION", "Caught std::exception: %s", e.what());
  } catch (...) {
    __android_log_print(ANDROID_LOG_ERROR, "EXCEPTION", "Caught unknown exception!!");
  }
}

And it logs

11-29 17:50:54.049 31176 31176 E EXCEPTION: Running exception test...
11-29 17:50:54.054 31176 31176 E EXCEPTION: Caught unknown exception!!

If you run the same code on iOS (replace log with NSLog), it works as expected:

11-29 17:50:54.049 31176 31176 E EXCEPTION: Running exception test...
11-29 17:50:54.054 31176 31176 E EXCEPTION: Caught std::exception: Test exception

So for some reason, the Android C++ lib fails to properly rethrow std::exception_ptr. ❌

iOS uses libc++ since ever.

Android uses libc++ since 2015, and apparently used libstdc++ (from GNU) before 2015 - could it be that libstdc++ is still used today somehow?
From what I'm seeing in RN's build.gradle, it correctly uses libc++: https://github.com/facebook/react-native/blob/91e217ff54e3bffb49454a723594d11669783e87/packages/react-native/ReactAndroid/build.gradle.kts#L535

Anyways... The code above does not work as expected. I think I read somewhere that exception_ptr does not work on ARMv5 since it needs some compare instruction that isn't available there, but afaik my device is ARMv8.

I have confirmed that;

  • ✅ It works in a blank Android C++ app
  • ✅ It works on iOS
  • ❌ It fails in a blank react-native Android app

Steps to reproduce

  1. Create a clean new app (npx create-expo-app@latest)
  2. Run npx expo prebuild
  3. Enable "build react-native from source" (by following these instructions)
  4. Add the above code to OnLoad.cpp
  5. Run npx expo android
  6. In adb, see exception_ptr not properly being castable

React Native Version

0.76.2

Affected Platforms

Runtime - Android

Output of npx react-native info

info Fetching system and libraries information...
System:
  OS: macOS 15.0.1
  CPU: (12) arm64 Apple M2 Pro
  Memory: 240.17 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.18.0
    path: ~/.nvm/versions/node/v18.18.0/bin/node
  Yarn:
    version: 1.22.19
    path: ~/.nvm/versions/node/v18.18.0/bin/yarn
  npm:
    version: 10.8.1
    path: ~/.nvm/versions/node/v18.18.0/bin/npm
  Watchman:
    version: 2024.11.11.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.1
      - iOS 18.1
      - macOS 15.1
      - tvOS 18.1
      - visionOS 2.1
      - watchOS 11.1
  Android SDK:
    API Levels:
      - "28"
      - "30"
      - "31"
      - "33"
      - "33"
      - "34"
      - "35"
    Build Tools:
      - 30.0.3
      - 31.0.0
      - 33.0.0
      - 33.0.1
      - 33.0.2
      - 34.0.0
      - 34.0.0
      - 35.0.0
    System Images:
      - android-33 | Google APIs ARM 64 v8a
      - android-34 | Google Play ARM 64 v8a
    Android NDK: 25.2.9519653
IDEs:
  Android Studio: 2024.2 AI-242.23339.11.2421.12550806
  Xcode:
    version: 16.1/16B40
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.13
    path: /opt/homebrew/opt/openjdk@17/bin/javac
  Ruby:
    version: 2.7.6
    path: /Users/mrousavy/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 15.1.2
    wanted: ^15.1.2
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.76.3
    wanted: 0.76.3
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

Stacktrace or Logs

11-29 17:50:54.049 31176 31176 E EXCEPTION: Running exception test...
11-29 17:50:54.054 31176 31176 E EXCEPTION: Caught unknown exception!!

Reproducer

https://github.com/mrousavy/react-native-exception_ptr-bug

Screenshots and Videos

No response

Activity

  1. react-native-bot commented on Nov 29, 2024

    @react-native-bot
    Collaborator

    Warning

    Could not parse version: We could not find or parse the version number of React Native in your issue report. Please use the template, and report your version including major, minor, and patch numbers - e.g. 0.76.2.

  2. react-native-bot commented on Nov 29, 2024

    @react-native-bot
    Collaborator

    Warning

    Could not parse version: We could not find or parse the version number of React Native in your issue report. Please use the template, and report your version including major, minor, and patch numbers - e.g. 0.76.2.

  3. mrousavy commented on Nov 29, 2024

    @mrousavy
    ContributorAuthor

    The CMakeLists.txt of the project where I added the code to OnLoad.cpp to also enables exceptions: https://github.com/facebook/react-native/blob/91e217ff54e3bffb49454a723594d11669783e87/packages/react-native/ReactAndroid/src/main/jni/react/jni/CMakeLists.txt#L11-L14

    I also added -frtti to those options and rebuilt the app, but it still doesn't work.

  4. changed the title [-]C++ STL Library used does not support `exception_ptr`[/-] [+]C++ STL Library on Android does not support `exception_ptr`[/+] on Nov 29, 2024
  5. NickGerleman commented on Nov 30, 2024

    @NickGerleman
    Contributor

    could it be that libstdc++ is still used today somehow?

    Nope. We are using libc++. When we bumped to NDK 26, this got bumped to LLVM 17. IIRC latest beta NDK uses libc++ based on LLVM 19.

    All of the build logic we control should also have RTTI enabled I think. I could imagine weirdness happening if a library is using static STL, and RN is using shared STL (so we have different copies of exception types/ODR issues), or if NDK is setting some special flags that XCode isn't. IIRC libc++ had some different ways of being able to implement RTTI, which we do not fuss with ourselves.

  6. mrousavy commented on Dec 2, 2024

    @mrousavy
    ContributorAuthor

    hm, I can't seem to pinpoint it. It's definitely broken in a blank app created with the expo 52 template bootstrapper.

  7. cortinico commented on Dec 3, 2024

    @cortinico
    Contributor

    @mrousavy have you tried on a vanilla Android App without React Native?

  8. mrousavy commented on Dec 3, 2024

    @mrousavy
    ContributorAuthor

    @cortinico Yep, in a blank new Android C++ template it works:

    Screenshot 2024-12-03 at 12 05 28

  9. cortinico commented on Dec 3, 2024

    @cortinico
    Contributor

    @cortinico Yep, in a blank new Android C++ template it works:

    Screenshot 2024-12-03 at 12 05 28

    We would have to diff the compilation flag you're using for your native-lib.cpp vs the one used for React Native OnLoad.cpp file. The latter are listed here: https://github.com/facebook/react-native/blob/67bff8734f4b92fe399910eecad5b67511a749c1/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake#L53-L67

  10. 57 remaining items

  11. cortinico commented on Mar 4, 2025

    @cortinico
    Contributor

    This should now be fixed with today's nightly @mrousavy please check and let me know if the issue is resolved

  12. mrousavy commented on Mar 4, 2025

    @mrousavy
    ContributorAuthor

    exciting!! I'll try this thank you so much

  13. Ashoat commented on May 5, 2025

    @Ashoat
    Contributor

    Is there any patch we can apply to get around this issue for current versions of React Native? In our case, our code for catching exceptions in C++ is broken on Android, and it looks like to use the patch we'd need to update our project to build React Native / Yoga from source on Android, or publish and use our own artifacts.

  14. ospfranco commented on May 5, 2025

    @ospfranco
    Contributor

    @Ashoat You need to catch the generic std::runtime_error and std::exception

    https://github.com/OP-Engineering/op-sqlite/blob/main/cpp/DBHostObject.cpp#L313

  15. cortinico commented on May 6, 2025

    @cortinico
    Contributor

    Is there any patch we can apply to get around this issue for current versions of React Native? In our case, our code for catching exceptions in C++ is broken on Android, and it looks like to use the patch we'd need to update our project to build React Native / Yoga from source on Android, or publish and use our own artifacts.

    Nope that's not easily backportable because of how complex the fix was

  16. cortinico commented on May 6, 2025

    @cortinico
    Contributor

    @Ashoat actually, the fix itself is sort of trivial. The problem is that it needs to be applied on top of 0.79 and I suspect it won't work well on other versions of RN

  17. Ashoat commented on May 6, 2025

    @Ashoat
    Contributor

    If a patch version of 0.79 could be released with this fix, that would be amazing! Or alternately, if there's a simple patch you can share that works with 0.79 (ie. doesn't require building React Native for Android from source) that would be good too.

  18. cortinico commented on May 6, 2025

    @cortinico
    Contributor

    If a patch version of 0.79 could be released with this fix, that would be amazing! Or alternately, if there's a simple patch you can share that works with 0.79 (ie. doesn't require building React Native for Android from source) that would be good too.

    Nope there is no patch that won't require building from source, because this has to do to how our native C++ code is precompiled. We'll have to potentially cherry-pick it inside 0.79 but is going to be a stack of several commits so not really easy

  19. Ashoat commented on Jun 2, 2025

    @Ashoat
    Contributor

    Hey @cortinico, was great seeing your talk at App.js this last week! Wanted to check on this issue, if there's any chance of patching this in React Native 0.79, or alternately if there's a React Native 0.80 coming soon that will be compatible with Expo 53. Ultimately we're blocked on upgrading due to this, so would be great to have a path forward. Hope you're doing well :)

  20. cortinico commented on Jun 2, 2025

    @cortinico
    Contributor

    if there's any chance of patching this in React Native 0.79, or alternately if there's a React Native 0.80 coming soon that will be compatible with Expo 53.

    This is coming in 0.80 that will be shipped sometime in the immediate future (trust me :))
    As mentioned, it's a bit of a pain to backport in a patch release as it could break compatibilities with codegen libraries (as we're modifying the template here).

  21. trcrsired commented on Sep 6, 2026

    @trcrsired

    just ban C++ EHs. C++EH is a mistake

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

    Type: New ArchitectureIssues and PRs related to new architecture (Fabric/Turbo Modules)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions