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

Android + Fabric : ANR on TextInput #687

Closed
mlecoq opened this issue Nov 14, 2024 · 10 comments · Fixed by #691
Closed

Android + Fabric : ANR on TextInput #687

mlecoq opened this issue Nov 14, 2024 · 10 comments · Fixed by #691
Assignees
Labels
🤖 android Android specific 🐛 bug Something isn't working 🏭 fabric Changes specific to new (fabric/jsi) architecture focused input 📝 Anything about focused input functionality

Comments

@mlecoq
Copy link

mlecoq commented Nov 14, 2024

Describe the bug
Since my app is on fabric, I have many ANR on text input

here is one of the stack traces

io.sentry.android.core.ApplicationNotResponding: ANR
    atsyscall
    at__futex_wait_ex
    atNonPI::MutexLockWithTimeout
    atoffset 4a8000) (std::__ndk1::mutex::lock
    atoffset 12b8000) (facebook::react::Binding::schedulerDidFinishTransaction
    atoffset 12b8000) (facebook::react::Scheduler::uiManagerDidFinishTransaction
    atoffset 12b8000) (facebook::react::UIManager::shadowTreeDidFinishTransaction const
    atoffset 12b8000) (facebook::react::ShadowTree::mount const
    atoffset 12b8000) (facebook::react::ShadowTree::tryCommit const
    atoffset 12b8000) (facebook::react::ShadowTree::commit const
    at
    atoffset 12b8000) (facebook::react::ShadowTreeRegistry::visit const
    atoffset 1900000) (reanimated::NativeReanimatedModule::performOperations
    atoffset 1900000) (facebook::jni::detail::MethodWrapper<void , &reanimated::NativeProxy::performOperations, reanimated::NativeProxy, void>::dispatch
    atoffset 1900000) (facebook::jni::detail::FunctionWrapper<void , facebook::jni::detail::JTypeFor<facebook::jni::HybridClass<reanimated::NativeProxy, facebook::jni::detail::BaseHybridClass>::JavaPart, facebook::jni::JObject, void>::_javaobject*, void>::call
    at com.swmansion.reanimated.NativeProxy.performOperations
    at com.swmansion.reanimated.NodesManager.performOperations(NodesManager.java:225)
    at com.swmansion.reanimated.NodesManager.onEventDispatch(NodesManager.java:337)
    at com.facebook.react.uimanager.events.FabricEventDispatcher.dispatchEvent(FabricEventDispatcher.java:71)
    at com.reactnativekeyboardcontroller.extensions.ThemedReactContextKt.dispatchEvent(ThemedReactContext.kt:23)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver.dispatchEventToJS(FocusedInputObserver.kt:163)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver.syncUpLayout(FocusedInputObserver.kt:153)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver.layoutListener$lambda$0(FocusedInputObserver.kt:57)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver.$r8$lambda$l4n8HFqvwhvLaxfgqXOCa3idsFI(unavailable:0)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver$$ExternalSyntheticLambda0.onLayoutChange(D8$$SyntheticClass:0)
    at android.view.View.layout(View.java:25180)
    at com.facebook.react.fabric.mounting.SurfaceMountingManager.updateLayout(SurfaceMountingManager.java:849)
    at com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem.execute(IntBufferBatchMountItem.java:140)
    at com.facebook.react.fabric.mounting.MountItemDispatcher.executeOrEnqueue(MountItemDispatcher.java:387)
    at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchMountItems(MountItemDispatcher.java:293)
    at com.facebook.react.fabric.mounting.MountItemDispatcher.tryDispatchMountItems(MountItemDispatcher.java:126)
    at com.facebook.react.fabric.FabricUIManager$3.runGuarded(FabricUIManager.java:831)
    at com.facebook.react.bridge.GuardedRunnable.run(GuardedRunnable.java:29)
    at com.facebook.react.fabric.FabricUIManager.scheduleMountItem(FabricUIManager.java:835)
    at com.facebook.react.fabric.BindingImpl.reportMount
    at com.facebook.react.fabric.FabricUIManager$MountItemDispatchListener$1.run(FabricUIManager.java:1276)
    at android.os.Handler.handleCallback(Handler.java:959)
    at android.os.Handler.dispatchMessage(Handler.java:100)

it always deal with

   at com.facebook.react.uimanager.events.FabricEventDispatcher.dispatchEvent(FabricEventDispatcher.java:71)
   at com.reactnativekeyboardcontroller.extensions.ThemedReactContextKt.dispatchEvent(ThemedReactContext.kt:23)
   at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver.dispatchEventToJS(FocusedInputObserver.kt:163)

and the issue is not systematic (first try sometimes works fine)

Code snippet
I don't use directly the api on concerned screen, I just have KeyboardProvider in my App.tsx file

Repo for reproducing
I will try to make one soon

To Reproduce

  1. Go to screen with input text
  2. Tap on it (to get focus)
  3. The app is frozen

Smartphone (please complete the following information):

  • Desktop OS: macOs 14.6.1
  • Device: reproduced on several devices: Samsung (phones and tabs), Redmi ...
  • OS: Android 14
  • RN version: 0.76.1
  • RN architecture: new
  • JS engine: Hermes
  • Library version: 1.14.4
@kirillzyusko kirillzyusko added 🐛 bug Something isn't working 🤖 android Android specific focused input 📝 Anything about focused input functionality labels Nov 14, 2024
@kirillzyusko
Copy link
Owner

@mlecoq which reanimated version do you use?

keyboard-controller intercepts TextInput events, so when you focus input or blur it then keyboard-controller will intercept these events and will dispatch them to JS as well... But I'm really curious how it can produce race conditions 🤔

@kirillzyusko kirillzyusko added the 🏭 fabric Changes specific to new (fabric/jsi) architecture label Nov 14, 2024
@mlecoq
Copy link
Author

mlecoq commented Nov 14, 2024

seems to be related to #683 - when I remove animated components on the screen, the crash does not occur

@mlecoq
Copy link
Author

mlecoq commented Nov 14, 2024

@mlecoq which reanimated version do you use?

keyboard-controller intercepts TextInput events, so when you focus input or blur it then keyboard-controller will intercept these events and will dispatch them to JS as well... But I'm really curious how it can produce race conditions 🤔

3.16.1

@mlecoq
Copy link
Author

mlecoq commented Nov 14, 2024

in other cases we see reanimated calls first

io.sentry.android.core.ApplicationNotResponding: Background ANR
    atsyscall
    at__futex_wait_ex
    atNonPI::MutexLockWithTimeout
    atoffset 4a8000) (std::__ndk1::mutex::lock
    atoffset 12b8000) (facebook::react::Binding::schedulerDidFinishTransaction
    atoffset 12b8000) (facebook::react::Scheduler::uiManagerDidFinishTransaction
    atoffset 12b8000) (facebook::react::UIManager::shadowTreeDidFinishTransaction const
    atoffset 12b8000) (facebook::react::ShadowTree::mount const
    atoffset 12b8000) (facebook::react::ShadowTree::tryCommit const
    atoffset 12b8000) (facebook::react::ShadowTree::commit const
    at
    atoffset 12b8000) (facebook::react::ShadowTreeRegistry::visit const
    atoffset 1900000) (reanimated::NativeReanimatedModule::performOperations
    atoffset 1900000) (facebook::jni::detail::MethodWrapper<void , &reanimated::NativeProxy::performOperations, reanimated::NativeProxy, void>::dispatch
    atoffset 1900000) (facebook::jni::detail::FunctionWrapper<void , facebook::jni::detail::JTypeFor<facebook::jni::HybridClass<reanimated::NativeProxy, facebook::jni::detail::BaseHybridClass>::JavaPart, facebook::jni::JObject, void>::_javaobject*, void>::call
    at com.swmansion.reanimated.NativeProxy.performOperations
    at com.swmansion.reanimated.NodesManager.performOperations(NodesManager.java:225)
    at com.swmansion.reanimated.NodesManager.onEventDispatch(NodesManager.java:337)
    at com.facebook.react.uimanager.events.FabricEventDispatcher.dispatchEvent(FabricEventDispatcher.java:71)
    at com.reactnativekeyboardcontroller.extensions.ThemedReactContextKt.dispatchEvent(ThemedReactContext.kt:23)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver.dispatchEventToJS(FocusedInputObserver.kt:163)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver.syncUpLayout(FocusedInputObserver.kt:153)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver$textListener$1.invoke(FocusedInputObserver.kt:60)
    at com.reactnativekeyboardcontroller.listeners.FocusedInputObserver$textListener$1.invoke(FocusedInputObserver.kt:59)
    at com.reactnativekeyboardcontroller.extensions.EditTextKt$addOnTextChangedListener$listener$1.onTextChanged(EditText.kt:48)
    at com.facebook.react.views.textinput.ReactEditText$TextWatcherDelegator.onTextChanged(ReactEditText.java:1344)
    at android.widget.TextView.sendOnTextChanged(TextView.java:12713)
    at android.widget.TextView.handleTextChanged(TextView.java:12828)
    at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:16246)
    at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:1268)
    at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:577)
    at androidx.emoji2.text.SpannableBuilder.replace(SpannableBuilder.java:315)
    at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:508)
    at androidx.emoji2.text.SpannableBuilder.replace(SpannableBuilder.java:305)
    at androidx.emoji2.text.SpannableBuilder.replace(SpannableBuilder.java:49)
    at com.facebook.react.views.textinput.ReactEditText.maybeSetText(ReactEditText.java:706)
    at com.facebook.react.views.textinput.ReactEditText.maybeSetTextFromState(ReactEditText.java:651)
    at com.facebook.react.views.textinput.ReactTextInputManager.updateExtraData(ReactTextInputManager.java:379)
    at com.facebook.react.views.textinput.ReactTextInputManager.updateExtraData(ReactTextInputManager.java:88)
    at com.facebook.react.fabric.mounting.SurfaceMountingManager.updateState(SurfaceMountingManager.java:935)
    at com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem.execute(IntBufferBatchMountItem.java:125)
    at com.facebook.react.fabric.mounting.MountItemDispatcher.executeOrEnqueue(MountItemDispatcher.java:387)
    at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchMountItems(MountItemDispatcher.java:293)
    at com.facebook.react.fabric.mounting.MountItemDispatcher.tryDispatchMountItems(MountItemDispatcher.java:126)
    at com.facebook.react.fabric.FabricUIManager$3.runGuarded(FabricUIManager.java:831)
    at com.facebook.react.bridge.GuardedRunnable.run(GuardedRunnable.java:29)
    at com.facebook.react.fabric.FabricUIManager.scheduleMountItem(FabricUIManager.java:835)
    at com.swmansion.reanimated.NativeProxy.performOperations
    at com.swmansion.reanimated.NodesManager.performOperations(NodesManager.java:225)
    at com.swmansion.reanimated.NodesManager.onEventDispatch(NodesManager.java:337)
    at com.swmansion.gesturehandler.ReanimatedEventDispatcher.sendEvent(ReanimatedEventDispatcher.kt:15)
    at com.swmansion.gesturehandler.react.RNGestureHandlerModule.sendEventForReanimated(RNGestureHandlerModule.kt:628)
    at com.swmansion.gesturehandler.react.RNGestureHandlerModule.onHandlerUpdate(RNGestureHandlerModule.kt:545)
    at com.swmansion.gesturehandler.react.RNGestureHandlerModule.access$onHandlerUpdate(RNGestureHandlerModule.kt:49)
    at com.swmansion.gesturehandler.react.RNGestureHandlerModule$eventListener$1.onHandlerUpdate(RNGestureHandlerModule.kt:314)
    at com.swmansion.gesturehandler.core.GestureHandler.dispatchHandlerUpdate(GestureHandler.kt:92)
    at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.deliverEventToGestureHandler(GestureHandlerOrchestrator.kt:291)
    at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.deliverEventToGestureHandlers(GestureHandlerOrchestrator.kt:234)
    at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.onTouchEvent(GestureHandlerOrchestrator.kt:50)
    at com.swmansion.gesturehandler.react.RNGestureHandlerRootHelper.dispatchTouchEvent(RNGestureHandlerRootHelper.kt:102)
    at com.swmansion.gesturehandler.react.RNGestureHandlerRootView.dispatchTouchEvent(RNGestureHandlerRootView.kt:36)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3125)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2806)
    at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:496)
    at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1952)
    at android.app.Activity.dispatchTouchEvent(Activity.java:4510)
    at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:70)
    at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:454)
    at android.view.View.dispatchPointerEvent(View.java:16548)
    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:7559)
    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:7326)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6723)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6780)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6746)
    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6912)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6754)
    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6969)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6727)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6780)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6746)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6754)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6727)
    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:9827)
    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:9778)
    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:9747)
    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9969)
    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:295)
    at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents
    at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:259)
    at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:9926)
    at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:10060)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1406)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415)
    at android.view.Choreographer.doCallbacks(Choreographer.java:1015)
    at android.view.Choreographer.doFrame(Choreographer.java:938)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389)
    at android.os.Handler.handleCallback(Handler.java:959)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loopOnce(Looper.java:232)
    at android.os.Looper.loop(Looper.java:317)
    at android.app.ActivityThread.main(ActivityThread.java:8592)
    at java.lang.reflect.Method.invoke
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)

@kirillzyusko
Copy link
Owner

@mlecoq I spoke with @tomekzaw and he told me that the problem most likely is the same as software-mansion/react-native-reanimated#6418 (comment)

Can you try to build RN from source and enable allowRecursiveCommitsWithSynchronousMountOnAndroid flag? This flag should be enabled by default starting from RN 0.77, but in a meantime the only one solution is to patch it and build from source 😔

@mlecoq
Copy link
Author

mlecoq commented Nov 14, 2024

Ok I will try that, thanks @kirillzyusko

@kirillzyusko
Copy link
Owner

@mlecoq please, keep me updated how it goes 🙏

@mlecoq
Copy link
Author

mlecoq commented Nov 14, 2024

@kirillzyusko I confirm that the flag fixes this issue and #683

@kirillzyusko
Copy link
Owner

@mlecoq awesome! Did you built RN from source? Or found the other way to enable this flag?

@mlecoq
Copy link
Author

mlecoq commented Nov 15, 2024

I had to build rn from source

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 android Android specific 🐛 bug Something isn't working 🏭 fabric Changes specific to new (fabric/jsi) architecture focused input 📝 Anything about focused input functionality
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants