react-native-reanimated: Inconsistent freezing on iOS

Description

Apologies in advance for vagueness, pretty hard to debug this one.

For the past few weeks I’ve been experiencing random freezing of our app, where the app seemingly stops in its tracks with no crashing/stacktrace/error. Initially I thought this was due to excessive re-rendering or a memory leak, but after reworking our logic to background actions the random freezes continue. Could well still be an error on our side, but struggling to see where/how.

I’ve tried to debug this myself with little joy (can’t remotely debug with reanimated) - the only nuggets of information I’ve managed to link are EXC_BAD_ACCESS exceptions which all seem to come from reanimated.

For reference, we’re using both react-native’s Animated and reanimated (in different parts of the app), and also frequently use Modalize which itself uses reanimated.

I found a previous issue that looks pretty similar to this but was fixed last year: https://github.com/software-mansion/react-native-reanimated/issues/1284

Expected behavior

No freezes

Actual behavior & steps to reproduce

Unknown

Snack or minimal code example

Can’t provide a replication unfortunately, but can provide some Sentry error traces from these exceptions.

EXC_BAD_ACCESS
XTUM > Stack overflow in _ZNKSt3__116__hash_node_baseIPNS_11__hash_nodeINS_17__hash_value_typeIiNS_6vectorINS_10shared_ptrIN8facebook3jsi5ValueEEENS_9allocatorIS8_EEEEEEPvEEE6__hashEv
Called from reanimated::StoreUser::~StoreUser::lambda::operator()
EXC_BAD_ACCESS
targetTimestamp > Attempted to dereference garbage pointer 0xce990e2ba698.
Called from reanimated::createReanimatedModule::lambda::operator()
EXC_BAD_ACCESS
Exception 1, Code 2752, Subcode 8 > Attempted to dereference garbage pointer 0xac0.
Called from reanimated::createReanimatedModule::lambda::operator()

Package versions

  • React Native: 0.64.1
  • React Native Reanimated: ^2.2.0
  • NodeJS: v14.15.5
  • Xcode: 12.5.1 (12E507)
  • Java & Gradle: Not relevant, we’re iOS only

For reference

  • react-native-modalize: ^2.0.8
  • react-native-portalize: ^1.0.7
  • react-native-screens: 2.17.1
  • @react-navigation/native: ^5.9.2
  • @react-navigation/stack: ^5.14.2

Affected platforms

  • Android
  • iOS
  • Web

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 9
  • Comments: 28 (4 by maintainers)

Most upvoted comments

As stated here before by @effektsvk - this seems to be related to https://github.com/facebook/react-native/issues/32329

This causes issues with all libraries that are using Reanimated 2 for animations, starting from RN 0.65.1 (react-native-modal, react-native-screens, react-navigation and a few more).

Seems like it’s something with the transition that keeps the native screen in memory, and on top of the main view, leading to an overlay that prevents touch events.

@piaskowyk @Szymon20000 , I saw you were working on RN~66 support in https://github.com/software-mansion/react-native-reanimated/pull/2462 - any idea what could be done to workaround this issue? Any plan for a fix?

I dont know what is your code that produces this error, but i was facing the same issue when i was using Gesture Detectors.

“react-native-gesture-handler”: “^2.4.0” “react-native-reanimated”: “^2.10.0”

What didnt work: Updating react-native-reantimated from 2.10.0 -> 2.13.0 Enabling Hermes Engine.

Code that made my app freeze (iOS, Android)

const pangGesture = Gesture.Pan() .onUpdate(e => { const leafsLength = Math.floor(e.x / 42); runOnJS(onPressHandler)(leafsLength); }) .onEnd(() => runOnJS(getRatedColor)());

By chaining runOnJS(true) to detector solved my issue. const pangGesture = Gesture.Pan() .runOnJS(true) .onUpdate(e => { const leafsLength = Math.floor(e.x / 42); runOnJS(onPressHandler)(leafsLength); }) .onEnd(() => runOnJS(getRatedColor)());

Hey, just a small note, there’s new 2.2.3 version that should help for now.

Getting a similar problem

Screen Shot 2021-08-05 at 5 30 58 pm

Problem resolved since version 3.+, so I encourage to upgrade 🎉

I can confirm that updating to react-native-reanimated@2.2.3 fixes this issue.

@Sanglepp This might be completely separate issue, but I upgraded react-native to 0.66.0 (react-native-reanimated as well) and I started having similar issues with Modal too. It looks like a RN bug, more info here: https://github.com/facebook/react-native/issues/32329. Just wanted to let you know.

i’ve crash cause of useAnimatedReaction. EXC_BAD_ACCESS

I’ve trawled through a variety of issues trying to diagnose this (see #1284 #2775 #2327).

Today I found the component causing trouble - an Animated Gradient I’d built a year back and forgotten about. The code is here: https://gist.github.com/lucasjohnston/fa6e9c66092664dcef09c42d5149087d It roughly does the following:

  • Create a gradient multiples times bigger than the element (defaults to 6x)
  • Uses a custom function called “interpolate” to set an X,Y co-ordinate
  • Applies useAnimatedStyle() to the <View /> to transform to those co-ordinates
  • Uses the useAnimatedStyle func to trigger a callback on the “interpolate” func on the JS thread, using Shared Values, to trigger an animation to a new set of co-ordinates
  • When generating new X,Y co-ordinates, the angles between the last and current set are compared to ensure it doesn’t look like the animation is just going back and forth in the same direction. The diff must be >15 or <-15.

When using the component, typically after ~5mins of running or immediately when starting to run, the random XY coordinates generated become very small and it takes >50 attempts to find an angle diff big enough. Normally this loop completes after just 1 or 2 attempts. I think this is down to the way RN / iOS handles randomness.

Screenshot 2022-03-31 at 20 21 23

It seems this is what causes the app to freeze up – I don’t get why, though. The component uses runOnJS() so shouldn’t be doing anything to stop the UI thread, and it’s called as a 'worklet' from useAnimatedStyle() so shouldn’t be blocking the main JS thread either? None of the code depends on a transform to be made.

Screenshot 2022-03-31 at 20 06 47

It might loop multiple times, but the console reports shows that my interpolate func does still resolve the loop. The app continues to be frozen though, and Xcode highlights the getProperty() of a SharableValue when paused.

Screenshot 2022-03-31 at 14 57 57

My expectation was that an infinitely loop would freeze, but a resolved loop would ultimately resolve itself even if there’s some lag. I’d also expect the app to crash, or RN to report some sort of error. None of this happens.

My guess is this being something to do with the way useAnimatedStyle().callback and runOnJS interact when a function is using Reanimated Shared Values.

Anyway – to avoid this, I’ve just removed the loop. If the angle isn’t big enough, we just add some arbitrary values to the XY coords and hope for the best.

@effektsvk Hey, so it works well with RN 0.66 and reanimated 2.2.3?

@hukpavlo Yes, I didn’t have any issues with those versions, and lot of others said that it’s working fine for them as well in the RN thread (https://github.com/facebook/react-native/issues/32329#issuecomment-943324655)

I can also confirm that 2.2.3 does work, while 2.3.0-beta.2 does not- is there a regression here?