react-native-reanimated: App crashes on reload in development mode with JSC Engine

Description

After upgrading to react-native-reanimated v3, we noticed that app crashes on reload in development mode with JSC engine. It’s reproducible in Example/ app in react-native-reanimated repo and can confirm it does not happen with hermes engine enabled.

Steps to reproduce

  1. Disable hermes in Example/ios/Podfile file by changing :hermes_enabled => flags[:hermes_enabled], :fabric_enabled => flags[:fabric_enabled], to :hermes_enabled => false, :fabric_enabled => false,
  2. reinstall pods by running pod install command from Example/ios folder
  3. build the app and launch it
  4. reload the app with R or devmode

Thank you :raised:

Snack or a link to a repository

https://github.com/ykliuiev/reanimated-crash-repro

Reanimated version

3.3.0

React Native version

0.72.3

Platforms

iOS

JavaScript runtime

JSC

Workflow

React Native (without Expo)

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

No response

Acknowledgements

Yes

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 22
  • Comments: 44 (6 by maintainers)

Most upvoted comments

Here’s an update: we investigated the issue and found the root cause of the problem.

Before we come up with a proper fix, here’s a workaround:

JSCRuntime.cpp

 JSCRuntime::~JSCRuntime() {
   // On shutting down and cleaning up: when JSC is actually torn down,
   // it calls JSC::Heap::lastChanceToFinalize internally which
   // finalizes anything left over.  But at this point,
   // JSValueUnprotect() can no longer be called.  We use an
   // atomic<bool> to avoid unsafe unprotects happening after shutdown
   // has started.
   ctxInvalid_ = true;
   JSGlobalContextRelease(ctx_);
-#ifndef NDEBUG
-  assert(
-      objectCounter_ == 0 && "JSCRuntime destroyed with a dangling API object");
-  assert(
-      stringCounter_ == 0 && "JSCRuntime destroyed with a dangling API string");
-#endif
}

@leontiy Unfortunately not and this is unlikely to change as we lean towards supporting only Hermes so JSC is not a priority at the moment.

I second this, this is a thing. I’ll try the suggested workaround meanwhile.

Edit: it does work, but i’m yet to find a way to patch this on the pods postinstall. Any suggestions on how to do it, while we wait for this to be fixed?.

@fellenabmb
I hope it helps you. Here is my patch based on @tomekzaw’s update.

react-native+0.72.4.patch

diff --git a/node_modules/react-native/ReactCommon/jsc/JSCRuntime.cpp b/node_modules/react-native/ReactCommon/jsc/JSCRuntime.cpp
index 7958519..5ecb903 100644
--- a/node_modules/react-native/ReactCommon/jsc/JSCRuntime.cpp
+++ b/node_modules/react-native/ReactCommon/jsc/JSCRuntime.cpp
@@ -409,12 +409,6 @@ JSCRuntime::~JSCRuntime() {
   // has started.
   ctxInvalid_ = true;
   JSGlobalContextRelease(ctx_);
-#ifndef NDEBUG
-  assert(
-      objectCounter_ == 0 && "JSCRuntime destroyed with a dangling API object");
-  assert(
-      stringCounter_ == 0 && "JSCRuntime destroyed with a dangling API string");
-#endif
 }
 
 std::shared_ptr<const jsi::PreparedJavaScript> JSCRuntime::prepareJavaScript(

Crash also happens (ios only) when doing a codepush update in the production app since it reloads the app in order to apply a new bundle. Would be great to at least get a workaround or a patch. cc @piaskowyk

@fellenabmb Steps would be:

  1. make the changes to that file in node_modules (node_modules/react-native/ReactCommon/jsc/JSCRuntime.cpp)
  2. run npx patch-package react-native
  3. Add the following to your package.json scripts
"scripts": {
+   "postinstall": "npx patch-package"
 }
  1. now everytime you run npm install or yarn it will also apply your change
  2. Delete your ios/Pods directory
  3. Last, run pod install. The RN package imports files straight from node_modules when installing the pods

Note: if you don’t have npx installed you’ll need to install patch-package in your project and remove the npx prefix from the commands

If you dont want to actually patch the package (since it’s probably not recommended to alter the React Native code) in production, you can make the changes manually locally, and start at step 5 above.

We will check it, but please give us a bit of time 🙏

Am I the only one also having this issue on Android? And for Android the suggested patch doesn’t work - probably because Android doesn’t use the JSCRuntime.cpp from node_modules but instead from the prebuilt AAR.

This issue is a bit more complicated, Tomek is still working on it in free time.

Same here! The app crashes whenever we reload the app in development mode and when hermes = false 😦

react-native: ^0.72.3
react-native-reanimated: ^3.3.0

Our team was forced to switch back to JSC since Hermes works terribly with Dates (https://github.com/facebook/hermes/issues/930)

@ykliuiev Thanks. I have tried all versions of 3.x and it seems happen all the time

I’m experiencing the same issues

  1. The JS bundle reloads after an OTA update – which throws this error in production as well
  2. JSC is a lot faster than Hermes in production which is why we’re opting to use JSC. Would love to switch to Hermes but we’re waiting for the performance to get a bit better first.
  3. The app works perfectly fine with Hermes

Please continue supporting JSC 🙏

rn 0.73.7 reanimated 3.8.1 hermes_enabled = false

I think most of the Intl APIs are now working with hermes @dwxw . We are still using JSC for iOS because we see significantly lower memory usage (which is quite surprising). It’s been a while since I checked the last time. The whole RN ecosystem is moving towards hermes, so I think what @tomekzaw says makes sense.

Here’s an update: we investigated the issue and found the root cause of the problem.

@tomekzaw is there an update on the fix? The suggested workaround introduces a potential memory corruption, so running the app is not safe / may have unspecified consequences.

If you are not facing the Hermes problems above (or they have already been fixed) but you are having trouble with hot reload, then you can try turning it on: https://reactnative.dev/docs/hermes#android

# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
-hermesEnabled=false
+hermesEnabled=true

Fixed for me with - rn 0.72.12 reanimated 3.6.0

I am not particularly using react-native-reanimated but I am using react-native-bottom-sheet that uses reanimated. My reanimated version is ^3.5.2 and bottom sheet is ^4, I am using JSC. Not Hermes.

I tried to remove the lines inside /react-native/ReactCommon/jsc/JSCRuntime.cpp and rebuilt the app again. Restarted the metro server as well with cache reset. But the app crashes every time when I reload the app in development mode. Is there anything I am doing wrong here? Thanks a lot for any guidance!

Thank you very much, you are awesome @tomekzaw

@tomekzaw @piaskowyk Please provide us with feedback, as we are experiencing an issue and need to resolve it quickly 🥺

Thank you very much

I’m also facing the same issue. Please kindly assist us by performing a quick check. Thank you.