Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NodesManager causing an app crash because of the "Map already consumed" #6004

Open
ddiachkov opened this issue May 10, 2024 · 2 comments
Open
Labels
Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided

Comments

@ddiachkov
Copy link

ddiachkov commented May 10, 2024

Description

We have an app that has a react-navigation entering animation for one of the screens. This screen has a fullscreen animation (Rive) playing in the background. Recently we've moved to the new arch and discovered that if you click on the animation it will crash the app because Reanimated tries to consume an event that was never meant to be consumed by it.

Stack Trace
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI: com.facebook.react.bridge.ObjectAlreadyConsumedException: Map already consumed
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.facebook.react.bridge.NativeMap.toString(Native Method)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.swmansion.reanimated.nativeProxy.EventHandler.receiveEvent(Native Method)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.swmansion.reanimated.nativeProxy.EventHandler.receiveEvent(EventHandler.java:25)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.facebook.react.uimanager.events.Event.dispatch(Event.java:167)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.swmansion.reanimated.NodesManager.handleEvent(NodesManager.java:328)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.swmansion.reanimated.NodesManager.onEventDispatch(NodesManager.java:314)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.facebook.react.uimanager.events.FabricEventDispatcher.dispatchEvent(FabricEventDispatcher.java:43)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.facebook.react.fabric.interop.InteropEventEmitter.receiveEvent(InteropEventEmitter.java:50)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.rivereactnative.RiveReactNativeView.4(RiveReactNativeView.kt:174)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.rivereactnative.RiveReactNativeView$listener$1.notifyPlay(RiveReactNativeView.kt:121)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at app.rive.runtime.kotlin.controllers.RiveFileController.notifyPlay(RiveFileController.kt:780)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at app.rive.runtime.kotlin.controllers.RiveFileController.play$kotlin_release(RiveFileController.kt:652)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at app.rive.runtime.kotlin.controllers.RiveFileController.pointerEvent(RiveFileController.kt:744)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at app.rive.runtime.kotlin.RiveAnimationView.onTouchEvent(RiveAnimationView.kt:978)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.View.dispatchTouchEvent(View.java:14309)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.swmansion.gesturehandler.react.RNGestureHandlerRootView.dispatchTouchEvent(RNGestureHandlerRootView.kt:38)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:488)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1871)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.app.Activity.dispatchTouchEvent(Activity.java:4125)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:70)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:446)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.View.dispatchPointerEvent(View.java:14568)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6016)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5819)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5310)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5485)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5542)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8080)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8031)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7992)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8203)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:220)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.os.MessageQueue.nativePollOnce(Native Method)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.os.MessageQueue.next(MessageQueue.java:335)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.os.Looper.loop(Looper.java:183)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at android.app.ActivityThread.main(ActivityThread.java:7656)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at java.lang.reflect.Method.invoke(Native Method)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
05-09 11:07:09.875 32364 32364 E MessageQueue-JNI:      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Root Cause

Reanimated installs custom EventDispatcherListener to listen to animation events, but it fails to validate that the incoming event does belong to the node it animates. That causes double consumption of WritableMap and app crash.

If you look at vanilla NativeAnimatedNodesManager, you can see that it calls event.getEventAnimationDriverMatchSpec() and matchSpec.match(driver.mViewTag, driver.mEventName) to filter the event. NodesManager does something similar, but only when the event is dispatched from non-UI thread.

Potential Fix

I moved the check to the top of the handleEvent:

diff --git a/android/src/main/java/com/swmansion/reanimated/NodesManager.java b/android/src/main/java/com/swmansion/reanimated/NodesManager.java
index b90b215b88009d2b46ea0dfa622faef597e2e1f4..c2445368cd41f032471a9758a91326827ec76fe6 100644
--- a/android/src/main/java/com/swmansion/reanimated/NodesManager.java
+++ b/android/src/main/java/com/swmansion/reanimated/NodesManager.java
@@ -323,18 +323,21 @@ public class NodesManager implements EventDispatcherListener {
     if (mNativeProxy == null) {
       return;
     }
+
+    // Check that we received an event for the node we own
+    String eventName = mCustomEventNamesResolver.resolveCustomEventName(event.getEventName());
+    int viewTag = event.getViewTag();
+    if (!mNativeProxy.isAnyHandlerWaitingForEvent(eventName, viewTag)) {
+      return;
+    }
+
     // Events can be dispatched from any thread so we have to make sure handleEvent is run from the
     // UI thread.
     if (UiThreadUtil.isOnUiThread()) {
       handleEvent(event);
       performOperations();
     } else {
-      String eventName = mCustomEventNamesResolver.resolveCustomEventName(event.getEventName());
-      int viewTag = event.getViewTag();
-      boolean shouldSaveEvent = mNativeProxy.isAnyHandlerWaitingForEvent(eventName, viewTag);
-      if (shouldSaveEvent) {
-        mEventQueue.offer(new CopiedEvent(event));
-      }
+      mEventQueue.offer(new CopiedEvent(event));
       startUpdatingOnAnimationFrame();
     }
   }

This seems to fix the issue. However, I am not 100% sure it won't cause some other bugs.

Steps to reproduce

  1. Create a Screen with some animation: <Stack.Screen options={{ animation: "slide_from_right" }} />
  2. Add an animation to it:
  3. Navigate to the screen and trigger some event, for example, touch the animation.

Snack or a link to a repository

https://github.com/ddiachkov/reanimated-0.73-crash-repro

Reanimated version

3.11.0

React Native version

0.73.5

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Fabric (New Architecture)

Build type

Release app & production bundle

Device

Real device

Device model

No response

Acknowledgements

Yes

@github-actions github-actions bot added Platform: Android This issue is specific to Android Missing repro This issue need minimum repro scenario Missing info The user didn't precise the problem enough Repro provided A reproduction with a snippet of code, snack or repo is provided and removed Missing repro This issue need minimum repro scenario labels May 10, 2024
@ddiachkov
Copy link
Author

Upon further investigation, I've found that the bug is not reproducible on 0.74 (or at least not as easy).

I've added minimal repro for 0.73. I think this corner case (mishandling events) is valid.

@github-actions github-actions bot removed the Missing info The user didn't precise the problem enough label May 10, 2024
@szydlovsky
Copy link
Contributor

Hi @ddiachkov! Seems like you got down to the bottom of the problem 😄 . I encourage you to create a PR with your fix proposal - then the team will be able to see themselves whether it risks any bugs or not. When you've created the PR, make sure to link it to this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided
Projects
None yet
Development

No branches or pull requests

2 participants