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

ConcurrentModificationException crash on Android #5822

Closed
Vepsur opened this issue Mar 21, 2024 · 8 comments · Fixed by #5918
Closed

ConcurrentModificationException crash on Android #5822

Vepsur opened this issue Mar 21, 2024 · 8 comments · Fixed by #5918
Assignees
Labels
Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided

Comments

@Vepsur
Copy link

Vepsur commented Mar 21, 2024

Description

I got a crash error in my Sentry in the production version of the app on Android

Sentry report:

ConcurrentModificationException java.util.HashMap$HashIterator in nextNode
mechanism: UncaughtExceptionHandler

Stack trace:

java.util.HashMap$HashIterator in nextNode at line 1574
java.util.HashMap$ValueIterator in next at line 1602
com.swmansion.reanimated.keyboard.KeyboardAnimationManager in notifyAboutKeyboardChange at line 44
com.swmansion.reanimated.keyboard.KeyboardAnimationManager$$ExternalSyntheticLambda0 in call at line 2
com.swmansion.reanimated.keyboard.WindowsInsetsManager in onApplyWindowInsetsListener at line 63
com.swmansion.reanimated.keyboard.WindowsInsetsManager in $r8$lambda$Gx1x4Lxu9gvvZb85XEKpmqU242U
com.swmansion.reanimated.keyboard.WindowsInsetsManager$$ExternalSyntheticLambda2 in onApplyWindowInsets at line 2
androidx.core.view.ViewCompat$Api21Impl$1 in onApplyWindowInsets at line 4858
android.view.View in dispatchApplyWindowInsets at line 12341
android.view.ViewGroup in dispatchApplyWindowInsets at line 7868
android.view.ViewRootImpl in dispatchApplyInsets at line 3683
android.view.ViewRootImpl in performTraversals at line 3963
android.view.ViewRootImpl in doTraversal at line 3248
android.view.ViewRootImpl$TraversalRunnable in run at line 11206
android.view.Choreographer$CallbackRecord in run at line 1650
android.view.Choreographer$CallbackRecord in run at line 1659
android.view.Choreographer in doCallbacks at line 1129
android.view.Choreographer in doFrame at line 1055
android.view.Choreographer$FrameDisplayEventReceiver in run at line 1622
android.os.Handler in handleCallback at line 958
android.os.Handler in dispatchMessage at line 99
android.os.Looper in loopOnce at line 230
android.os.Looper in loop at line 319
android.app.ActivityThread in main at line 8893
java.lang.reflect.Method in invoke
com.android.internal.os.RuntimeInit$MethodAndArgsCaller in run at line 608
com.android.internal.os.ZygoteInit in main at line 1103

I faced this bug in the dev environment. I solved it in debug mode on my Android via the created async hook, which waits while the keyboard closes and only then navigates to another screen.
But I got the error in my Sentry after releasing a new version with fixes, so I missed something.

P.S. I also suggest that can be related to react-native-keyboard-controller or react-native-screens enableFreeze(true) and will continue my investigation

22-mar updates:

  • It happens only if u using a top/bottom bar RN navigation
  • I reproduce it in our app if u navigate on the top bar navigator and immediately tap on text input/area
  • I fixed it by adding "lazy" property in the stack navigator, but can not be completely sure that it will fix in all cases and devices

5-apr updates:

  • It's not an issue of the tab navigation
  • It's an issue of using the useAnimatedKeyboard hook inside the items of FlatList
  • I created a reproduction repository and added a link to it

Steps to reproduce

  1. Tap on the Navigate to profile button

  2. Immediately after navigation, tap on text input

  3. The app should crash most of the time

  4. Tap on the Navigate to profile button

  5. After navigation, tap on text input

  6. While the keyboard is open, try scrolling FlatList

  7. The app should crash often enough

Snack or a link to a repository

reanimated-android-crash-example

Reanimated version

3.8.0

React Native version

0.72.6

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Paper (Old 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 labels Mar 21, 2024
@tomekzaw
Copy link
Member

Hi @Vepsur, thanks for reporting this issue. It looks like something related to useAnimatedKeyboard which we have recently refactored. Assigning our keyboard expert @piaskowyk.

@Vepsur
Copy link
Author

Vepsur commented Mar 22, 2024

Here are a few updates about the behavior of the crash:

  • It happens only if u using a top/bottom bar RN navigation
  • I reproduce it in our app if u navigate on the top bar navigator and immediately tap on text input/area
  • I fixed it by adding "lazy" property in the stack navigator, but can not be completely sure that it will fix in all cases and devices

And I will try to create a separate reproduction repository for that issue

@solitarysp
Copy link

solitarysp commented Mar 25, 2024

I also received the same error.

image

@github-actions github-actions bot added 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 Apr 5, 2024
@Vepsur
Copy link
Author

Vepsur commented Apr 5, 2024

Here are a few updates about the behavior of the crash:

  • It's not an issue of the tab navigation
  • It's an issue of using the useAnimatedKeyboard hook inside the items of FlatList
  • I created a reproduction repository and added a link to it
  • I will update the reproducing steps in the description

@Vepsur
Copy link
Author

Vepsur commented Apr 5, 2024

android-keyboard-renimated-crash (1)
android-keyboard-renimated-crash (2)

@tomekzaw
Copy link
Member

tomekzaw commented Apr 5, 2024

cc @maciekstosio

@maciekstosio
Copy link
Contributor

Hi, I posted PR (#5918) that should fix that. Let me know if it helps.

@Vepsur
Copy link
Author

Vepsur commented Apr 22, 2024

I checked it in the repo repository and in our project, it seems like it resolved this issue. Thanks!

github-merge-queue bot pushed a commit that referenced this issue May 1, 2024
## Summary

Fixes #5822

To keep track of all listeners we use hash map, and notify changes on
all of them. When quickly opening flat list with components that use
useAnimatedKeyboard and focus on some keyboard, the flat list is still
adding new components (adding new listeners), while listeners are
notified in the loop about the changes to the keyboard height. Changing
HashMap to ConcurrentHashMap seems to fix the issue.

|Before|After|
|-|-|
|<video
src="https://github.com/software-mansion/react-native-reanimated/assets/11800297/66d26b5e-3e81-492b-b692-50d63bc4ca0e"
/>|<video
src="https://github.com/software-mansion/react-native-reanimated/assets/11800297/bca99310-d4e1-4cfa-a83b-de3872c93f47"
/>|

## Test plan

<details>
<summary>Test component</summary>

```jsx
import React from 'react';
import {
  FlatList,
  SafeAreaView,
  StyleSheet,
  TextInput,
  View,
} from 'react-native';

import {useAnimatedKeyboard} from 'react-native-reanimated';

function Card() {
  useAnimatedKeyboard();

  return (
    <View
      style={StyleSheet.flatten({
        width: '100%',
        height: 100,
        backgroundColor: 'black',
        marginVertical: 4,
      })}
    />
  );
}
export default function ProfileScreen() {
  const array = Array(1000).fill(0);

  const renderHeader = () => (
    <View>
      <TextInput
        numberOfLines={10}
        placeholder="text input"
        style={StyleSheet.flatten({width: '100%', height: 500, borderWidth: 2})}
      />
    </View>
  );

  return (
    <SafeAreaView style={StyleSheet.flatten({padding: 16})}>
      <FlatList
        keyboardShouldPersistTaps="always"
        data={array}
        renderItem={() => <Card />}
        ListHeaderComponent={renderHeader}
      />
    </SafeAreaView>
  );
}

```

</details>
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

Successfully merging a pull request may close this issue.

5 participants