Skip to content

[Fabric] Crash on react_native_assert(attempts < 1024); #4660

Closed

Description

@tomekzaw

Description

This crash occurs when React Native tries to commit changes from a React render that takes long to calculate layout (in particular, more than one animation frame) while Reanimated animates some layout properties (e.g. width) on each animation frame.

Zrzut ekranu 2023-07-2 o 10 44 34
react_native_assert failure: attempts < 1024
Assertion failed: (attempts < 1024), function commit, file ShadowTree.cpp, line 314.

The root cause of starvation here is that Reanimated is able to commit a new tree way faster than React Native (e.g. due to layout calculation) and React Native's transaction goes out of date in terms of source shadow tree:

https://github.com/facebook/react-native/blob/259a31689334968d607978c8d335c6da444cc253/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp#L371-L373

Steps to reproduce

  1. Open FabricExample on iOS
  2. Open Chessboard example
  3. Wait for some time
  4. The app crashes on react_native_assert(attempts < 1024);

In order to simulate long layout calculation, you can paste the following line:

 RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
     ShadowTree const &shadowTree,
     RootShadowNode::Shared const &oldRootShadowNode,
     RootShadowNode::Unshared const &newRootShadowNode) const noexcept {
   if (propsRegistry_->isLastReanimatedRoot(newRootShadowNode)) {
     // ShadowTree commited by Reanimated, no need to apply updates from
     // PropsRegistry
     return newRootShadowNode;
   }
 
   // ShadowTree not commited by Reanimated, apply updates from PropsRegistry
        
+  for (int i = 0; i < 100000000; ++i);

   auto surfaceId = newRootShadowNode->getSurfaceId();

   auto rootNode = newRootShadowNode->ShadowNode::clone(ShadowNodeFragment{});

You can also decrease the attempts threshold:

     // After multiple attempts, we failed to commit the transaction.
     // Something internally went terribly wrong.
-    react_native_assert(attempts < 1024);
+    react_native_assert(attempts < 50);
   }

Snack or a link to a repository

none

Reanimated version

3.3.0

React Native version

0.72.0-rc.6

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

No response

Acknowledgements

Yes

Activity

  1. tomekzaw commented on Jul 2, 2023

    @tomekzaw
    MemberAuthor

    Workaround 1

    Edit ReanimatedCommitHook.cpp and remove the following piece of code:

     RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
         ShadowTree const &shadowTree,
         RootShadowNode::Shared const &oldRootShadowNode,
         RootShadowNode::Unshared const &newRootShadowNode) const noexcept {
    -  if (propsRegistry_->isLastReanimatedRoot(newRootShadowNode)) {
    -    // ShadowTree commited by Reanimated, no need to apply updates from
    -    // PropsRegistry
    -    return newRootShadowNode;
    -  }
    
       // ShadowTree not commited by Reanimated, apply updates from PropsRegistry
  2. billnbell commented on Jul 8, 2023

    @billnbell

    I am getting this too!

  3. snowdigital commented on Jul 27, 2023

    @snowdigital

    Maybe i have simular issue, when reanimated starts animating something it quickly bumps memory usage to maximum and crashes then, is it same?

  4. tomekzaw commented on Sep 11, 2023

    @tomekzaw
    MemberAuthor

    Fixed by @michalmaka in #4833.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions