react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

Deadlock in [REANodesManager performOperations]

Open cltnschlosser opened this issue 2 years ago β€’ 22 comments

Description

performOperations blocks the main queue while waiting for the UIManager queue to do work. It's possible that the UIManager queue is already blocked waiting to perform work on the main queue (See somewhat common usage of RCTUnsafeExecuteOnMainQueueSync). This can result in deadlock like the following:

Thread 0 Crashed:
0   libsystem_kernel.dylib        	0x00000001b82e7540 semaphore_wait_trap + 8
1   libdispatch.dylib             	0x00000001809ffc00 _dispatch_sema4_wait + 28 (lock.c:139)
2   libdispatch.dylib             	0x0000000180a002b8 _dispatch_semaphore_wait_slow + 132 (semaphore.c:132)
3   MyApp                        	0x0000000104795c64 -[REANodesManager performOperations] + 284 (REANodesManager.m:261)
4   MyApp                        	0x0000000104795aa4 -[REANodesManager onAnimationFrame:] + 452 (REANodesManager.m:209)
5   QuartzCore                    	0x0000000184a5e378 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 756 (CADisplay.mm:4177)
6   QuartzCore                    	0x0000000184a64fac display_timer_callback(__CFMachPort*, void*, long, void*) + 372 (CADisplayTimer.cpp:219)
7   CoreFoundation                	0x0000000180cff440 __CFMachPortPerform + 176 (CFMachPort.c:549)
8   CoreFoundation                	0x0000000180d427d4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 60 (CFRunLoop.c:1996)
9   CoreFoundation                	0x0000000180d45fe0 __CFRunLoopDoSource1 + 596 (CFRunLoop.c:2136)
10  CoreFoundation                	0x0000000180cffebc __CFRunLoopRun + 2380 (CFRunLoop.c:3172)
11  CoreFoundation                	0x0000000180d13468 CFRunLoopRunSpecific + 600 (CFRunLoop.c:3268)
12  GraphicsServices              	0x000000019c8b738c GSEventRunModal + 164 (GSEvent.c:2200)
13  UIKitCore                     	0x00000001836b65d0 -[UIApplication _run] + 1100 (UIApplication.m:3493)
14  UIKitCore                     	0x0000000183434f74 UIApplicationMain + 364 (UIApplication.m:5047)
15  MyApp                        	0x000000010421bf2c main + 68 (AnalyticsKey.swift:29)
16  dyld                          	0x0000000105e9daa4 start + 520 (dyldMain.cpp:879)
Thread 12:
0   libsystem_kernel.dylib        	0x00000001b82e81a4 __ulock_wait + 8
1   libdispatch.dylib             	0x0000000180a00064 _dlock_wait + 56 (lock.c:326)
2   libdispatch.dylib             	0x00000001809ffe08 _dispatch_thread_event_wait_slow + 56 (lock.c:366)
3   libdispatch.dylib             	0x0000000180a0ebac __DISPATCH_WAIT_FOR_QUEUE__ + 364 (lock.h:330)
4   libdispatch.dylib             	0x0000000180a0e754 _dispatch_sync_f_slow + 144 (queue.c:1762)
5   MyApp                        	0x0000000104849324 RCTUnsafeExecuteOnMainQueueSync + 120 (RCTUtils.m:277)
6   libdispatch.dylib             	0x00000001809ff670 _dispatch_client_callout + 20 (object.m:560)
7   libdispatch.dylib             	0x0000000180a00f18 _dispatch_once_callout + 32 (once.c:52)
8   MyApp                        	0x00000001048494e4 dispatch_once + 20 (once.h:84)
9   MyApp                        	0x00000001048494e4 RCTScreenSize + 68 (RCTUtils.m:343)
10  MyApp                        	0x0000000104815898 -[RCTModalHostShadowView insertReactSubview:atIndex:] + 124 (RCTModalHostViewManager.m:42)
11  MyApp                        	0x0000000104842ad0 RCTSetChildren + 280 (RCTUIManager.m:884)
12  MyApp                        	0x00000001048428e8 -[RCTUIManager setChildren:reactTags:] + 68 (RCTUIManager.m:865)
13  CoreFoundation                	0x0000000180d163a4 __invoking___ + 148
14  CoreFoundation                	0x0000000180d33b74 -[NSInvocation invoke] + 468 (NSForwarding.m:3378)
15  CoreFoundation                	0x0000000180d6a9d4 -[NSInvocation invokeWithTarget:] + 80 (NSForwarding.m:3475)
16  MyApp                        	0x000000010481b928 -[RCTModuleMethod invokeWithBridge:module:arguments:] + 460 (RCTModuleMethod.mm:584)
17  MyApp                        	0x000000010481df2c facebook::react::invokeInner(RCTBridge*, RCTModuleData*, unsigned int, folly::dynamic const&, int, (anonymous namespace)::SchedulingContext) + 540 (RCTNativeModule.mm:183)
18  MyApp                        	0x000000010481db5c operator() + 68 (RCTNativeModule.mm:104)
19  MyApp                        	0x000000010481db5c invocation function for block in facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int) + 112 (RCTNativeModule.mm:95)
20  libdispatch.dylib             	0x00000001809fd924 _dispatch_call_block_and_release + 32 (init.c:1517)
21  libdispatch.dylib             	0x00000001809ff670 _dispatch_client_callout + 20 (object.m:560)
22  libdispatch.dylib             	0x0000000180a06df4 _dispatch_lane_serial_drain + 672 (inline_internal.h:2601)
23  libdispatch.dylib             	0x0000000180a07968 _dispatch_lane_invoke + 392 (queue.c:3937)
24  libdispatch.dylib             	0x0000000180a121b8 _dispatch_workloop_worker_thread + 656 (queue.c:6727)
25  libsystem_pthread.dylib       	0x00000001f181b0f4 _pthread_wqthread + 288 (pthread.c:2599)
26  libsystem_pthread.dylib       	0x00000001f181ae94 start_wqthread + 8

There is some documentation in RCTUIManagerUtils.h on the threading model of this system. There is a noteworthy piece here:

This solution assumes that the code running on UIManager queue will never explicitly block the Main queue via calling RCTUnsafeExecuteOnMainQueueSync. Otherwise, it can cause a deadlock.

What is happening in performOperations is effectively a custom implementation of RCTUnsafeExecuteOnMainQueueSync and so we get deadlock.

This logic was introduced with https://github.com/software-mansion/react-native-reanimated/pull/1215, I don't fully understand the issue this was fixing or why this needed to be synchronously waiting, but there atleast is a connected issue with some context.

This pull request https://github.com/software-mansion/react-native-reanimated/pull/3082 could "fix" the issue by breaking the deadlock, but I'm thinking more could be improved here instead of just timing out the deadlock. It's also not clear to me what happens when this runs asynchronously instead of synchronously.

Potentially related: https://github.com/software-mansion/react-native-reanimated/issues/2938, https://github.com/software-mansion/react-native-reanimated/issues/2327 This same logic is also on Android, which is likely the root cause of https://github.com/software-mansion/react-native-reanimated/issues/3062 and https://github.com/software-mansion/react-native-reanimated/issues/2251

Expected behavior

Never deadlock. Generally best practice is to never block the main thread.

Actual behavior & steps to reproduce

performOperations blocks the main queue waiting on the UIManager queue. It's possible that at this same time the UIManager queue is already blocked trying to perform work on the main queue.

Snack or minimal code example

I don't have anything other than stacktraces showing the deadlock.

Package versions

name version
react-native 0.66.4
react-native-reanimated 2.4.1 (with https://github.com/software-mansion/react-native-reanimated/pull/2681 applied)
NodeJS 16.14.2
Xcode 13.3.1

Affected platforms

  • [x] Android (maybe)
  • [x] iOS

cltnschlosser avatar Apr 14 '22 20:04 cltnschlosser

Hey! πŸ‘‹

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snippet of code, a snack or a link to a GitHub repository that reproduces the problem?

github-actions[bot] avatar Apr 14 '22 20:04 github-actions[bot]

I have the same issue.

nazrdogan avatar Apr 20 '22 21:04 nazrdogan

same here

bsonmez avatar Apr 21 '22 11:04 bsonmez

same here

egorkhmelev avatar Apr 22 '22 08:04 egorkhmelev

same error w/ pretty similar stack trace, can only see this behaviour on iOS though. "react-native-reanimated": "^2.5.0"

dwnste avatar Apr 22 '22 12:04 dwnste

Also seeing this. iPhone7 and iPad mini. I'm still on react-native-reanimated 2.3.3 though.

ericgjackson avatar Apr 22 '22 22:04 ericgjackson

I can observe this issue using in the latest version (2.8.0) as well.

AlexanderEggers avatar Apr 27 '22 00:04 AlexanderEggers

I'm facing exactly the same one. Did you find a solution for that issue? Really appreciate that. Thank you guys

"@react-navigation/bottom-tabs": "^6.0.9", "@react-navigation/core": "^6.1.0", "@react-navigation/native": "^6.0.6", "@react-navigation/stack": "^6.0.11", "react-native-reanimated": "~2.3.3", "react-native-screens": "^3.13.1"

anhquan291 avatar Apr 28 '22 09:04 anhquan291

Same here

"react-native-reanimated": "2.3.1", "@react-navigation/bottom-tabs": "5.11.2", "@react-navigation/native": "~5.8.10", "@react-navigation/stack": "~5.12.8",

daxaxelrod avatar May 04 '22 15:05 daxaxelrod

Is anyone reviewing cltnschlosser's PR? Or fixing the problem in some other way?

ericgjackson avatar May 15 '22 23:05 ericgjackson

Samesies here! The iOS app works just fine but the android app refuses to change the screen.

"@react-navigation/devtools": "^6.0.7",
"@react-navigation/drawer": "^6.4.1",
"@react-navigation/native": "^6.0.10",
"@react-navigation/native-stack": "^6.6.2",
"react-native-reanimated": "^2.8.0",
"react-native": "0.68.1",

A simple workaround would be required just in the short term for us :-)

cedricjacobs avatar Jun 02 '22 11:06 cedricjacobs

Same

jp928 avatar Jun 14 '22 08:06 jp928

anybody here some thoughts on a workaround? I am still stuck and don't know how to resolve the matter as it is the navigation library that causes it. :-/

cedricjacobs avatar Jun 21 '22 20:06 cedricjacobs

same

3runoDesign avatar Jul 25 '22 20:07 3runoDesign

same here

lucascardial avatar Jul 26 '22 14:07 lucascardial

Any update on this?

tomgreco avatar Aug 04 '22 17:08 tomgreco

After merging in this PR locally, we saw a noticeable drop in iOS native app crashes over the last 90 days: Screen Shot 2022-08-04 at 10 35 03 AM

dandre-hound avatar Aug 04 '22 17:08 dandre-hound

same here

caopeng000 avatar Aug 19 '22 02:08 caopeng000

Hey! πŸ‘‹

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

github-actions[bot] avatar Aug 19 '22 02:08 github-actions[bot]

same here "react-native-reanimated": "2.9.1", "react-native": "0.64.2",

caopeng000 avatar Aug 19 '22 02:08 caopeng000

Same here

App crashes when you go back to foreground And randomly when open the app

"react-native-reanimated": "^2.10.0", "react-native": "0.67.4",

Captura de Pantalla 2022-08-26 a la(s) 10 07 25

In Pods RNReanimated > ios > REANodesManager > -performOperations Captura de Pantalla 2022-08-26 a la(s) 10 08 30

This crash it doesn't even get caught by Crashlytics

EmmanuelSalazarID avatar Aug 26 '22 15:08 EmmanuelSalazarID

Facing same issue on android multiple devices: React-native : 0.66.4 react-native-reanimated : 2.9.1 (^2.2 on package.json)

    "@ptomasroos/react-native-multi-slider": "^2.2.2",
    "@react-native-async-storage/async-storage": "^1.15.4",
    "@react-native-community/art": "https://github.com/react-native-art/art.git",
    "@react-native-community/blur": "^3.6.0",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-native-community/slider": "^3.0.3",
    "@react-native-firebase/analytics": "^11.5.0",
    "@react-native-firebase/app": "^11.5.0",
    "@react-native-firebase/crashlytics": "^11.5.0",
    "@react-native-firebase/messaging": "^11.5.0",
    "@react-native-firebase/perf": "^11.5.0",
    "@react-navigation/bottom-tabs": "^5.11.9",
    "@react-navigation/native": "^5.9.4",
    "@react-navigation/stack": "^5.14.4",
    "@reduxjs/toolkit": "^1.5.1",
    "@sentry/react-native": "^3.1.1",
    "@shopify/restyle": "^1.4.0",
    "@snowplow/react-native-tracker": "^1.2.1",
    "axios": "^0.21.1",
    "babel-plugin-module-resolver": "^4.1.0",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "clevertap-react-native": "^0.8.1",
    "launchdarkly-react-native-client-sdk": "^5.1.0",
    "lodash": "^4.17.21",
    "lottie-ios": "3.4.0",
    "lottie-react-native": "^5.1.3",
    "moment": "^2.29.1",
    "query-string": "^7.0.0",
    "react": "17.0.2",
    "react-native": "0.66.3",
    "react-native-branch": "^5.5.0",
    "react-native-code-push": "^7.0.4",
    "react-native-dash": "^0.0.11",
    "react-native-dropdown-picker": "5.0",
    "react-native-fast-image": "^8.3.4",
    "react-native-fbsdk-next": "^7.0.1",
    "react-native-flipper": "^0.91.2",
    "react-native-geocoding": "^0.5.0",
    "react-native-geolocation-service": "5.2.0",
    "react-native-gesture-handler": "^2.4.0",
    "react-native-image-pan-zoom": "^2.1.12",
    "react-native-in-app-review": "^3.2.3",
    "react-native-linear-gradient": "^2.5.6",
    "react-native-modal": "^13.0.1",
    "react-native-modal-dropdown": "^1.0.0",
    "react-native-neomorph-shadows": "^1.1.2",
    "react-native-otp-verify": "^1.0.4",
    "react-native-pager-view": "^5.1.9",
    "react-native-progress": "^5.0.0",
    "react-native-radial-gradient": "^1.0.9",
    "react-native-reanimated": "2.6.0",
    "react-native-render-html": "^6.3.4",
    "react-native-safe-area-context": "^3.2.0",
    "react-native-screens": "^3.1.1",
    "react-native-shimmer-placeholder": "^2.0.7",
    "react-native-simple-toast": "^1.1.3",
    "react-native-size-matters": "^0.4.0",
    "react-native-smooth-picker": "^1.1.5",
    "react-native-splash-screen": "^3.2.0",
    "react-native-svg": "^12.1.1",
    "react-native-svg-transformer": "^0.14.3",
    "react-native-tab-view": "^3.0.1",
    "react-native-tracking-transparency": "^0.1.1",
    "react-native-ultimate-config": "^3.3.4",
    "react-native-version-info": "^1.1.0",
    "react-native-video": "^5.2.0",
    "react-native-walkthrough-tooltip": "^1.3.0",
    "react-native-webview": "^11.4.0",
    "react-native-wheel-scrollview-picker": "^2.0.0",
    "react-redux": "^7.2.3",
    "redux-flipper": "^1.4.2",
    "redux-logger": "^3.0.6",
    "redux-persist": "^6.0.0",
    "yup": "^0.32.9"
  },```

viv3kk avatar Sep 22 '22 12:09 viv3kk

I got the same issue when using @react-native-community/[email protected]. but there was no issue with @react-native-community/[email protected]. there was only one change added to 6.3.3: https://github.com/react-native-datetimepicker/datetimepicker/releases/tag/v6.3.3. the app hangs (sometimes) when focusing on the input with DateTimePicker. I tried with reanimated 2.10.0, 2.11.0 and 3.0.0-rc.3.

the crash logs are very similar to what @cltnschlosser had:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	    0x7fff60c529b6 semaphore_wait_trap + 10
1   libdispatch.dylib             	    0x7fff201069a0 _dispatch_sema4_wait + 16
2   libdispatch.dylib             	    0x7fff20106e9f _dispatch_semaphore_wait_slow + 98
3   MyApp                      	        0x10bd4fcbd -[REANodesManager performOperations] + 429 (REANodesManager.m:277)
4   MyApp                      	        0x10bd4f927 -[REANodesManager onAnimationFrame:] + 791 (REANodesManager.m:225)
5   QuartzCore                    	    0x7fff2794a369 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 755
6   QuartzCore                    	    0x7fff27a2fd78 display_timer_callback(__CFMachPort*, void*, long, void*) + 639
7   CoreFoundation                	    0x7fff2035c9d8 __CFMachPortPerform + 157
8   CoreFoundation                	    0x7fff2038fc82 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
9   CoreFoundation                	    0x7fff2038f023 __CFRunLoopDoSource1 + 614
10  CoreFoundation                	    0x7fff203894f2 __CFRunLoopRun + 2353
11  CoreFoundation                	    0x7fff203886d6 CFRunLoopRunSpecific + 567
12  GraphicsServices              	    0x7fff2bededb3 GSEventRunModal + 139
13  UIKitCore                     	    0x7fff24690e0b -[UIApplication _run] + 912
14  UIKitCore                     	    0x7fff24695cbc UIApplicationMain + 101
15  MyApp                      	        0x10b53b328 main + 104 (main.m:8)
16  dyld                          	    0x11a84652e start + 462
Thread 2::  Dispatch queue: com.facebook.react.ShadowQueue
0   libsystem_kernel.dylib        	    0x7fff60c540ea __ulock_wait + 10
1   libdispatch.dylib             	    0x7fff20106d09 _dlock_wait + 44
2   libdispatch.dylib             	    0x7fff20106b6c _dispatch_thread_event_wait_slow + 40
3   libdispatch.dylib             	    0x7fff20113e68 __DISPATCH_WAIT_FOR_QUEUE__ + 316
4   libdispatch.dylib             	    0x7fff201139ec _dispatch_sync_f_slow + 199
5   MyApp                      	        0x10bc5e38e RNDateTimePickerShadowViewMeasure + 238 (RNDateTimePickerShadowView.m:39)
6   MyApp                      	        0x10c25fb35 YGNode::measure(float, YGMeasureMode, float, YGMeasureMode, void*) + 133 (YGNode.cpp:175)
7   MyApp                      	        0x10c276679 YGNodeWithMeasureFuncSetMeasuredDimensions(YGNode*, float, float, YGMeasureMode, YGMeasureMode, float, float, facebook::yoga::LayoutData&, void*, facebook::yoga::LayoutPassReason) + 761 (Yoga.cpp:1692)
8   MyApp                      	        0x10c26e443 YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 1171 (Yoga.cpp:2761)
9   MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
10  MyApp                      	        0x10c27ae11 YGNodeComputeFlexBasisForChild(YGNode*, YGNode*, float, YGMeasureMode, float, float, float, YGMeasureMode, YGDirection, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2865 (Yoga.cpp:1410)
11  MyApp                      	        0x10c2771c2 YGNodeComputeFlexBasisForChildren(YGNode*, float, float, YGMeasureMode, YGMeasureMode, YGDirection, YGFlexDirection, YGConfig*, bool, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 1010 (Yoga.cpp:1930)
12  MyApp                      	        0x10c26e8ce YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 2334 (Yoga.cpp:2859)
13  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
14  MyApp                      	        0x10c27ae11 YGNodeComputeFlexBasisForChild(YGNode*, YGNode*, float, YGMeasureMode, float, float, float, YGMeasureMode, YGDirection, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2865 (Yoga.cpp:1410)
15  MyApp                      	        0x10c2771c2 YGNodeComputeFlexBasisForChildren(YGNode*, float, float, YGMeasureMode, YGMeasureMode, YGDirection, YGFlexDirection, YGConfig*, bool, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 1010 (Yoga.cpp:1930)
16  MyApp                      	        0x10c26e8ce YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 2334 (Yoga.cpp:2859)
17  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
18  MyApp                      	        0x10c27ae11 YGNodeComputeFlexBasisForChild(YGNode*, YGNode*, float, YGMeasureMode, float, float, float, YGMeasureMode, YGDirection, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2865 (Yoga.cpp:1410)
19  MyApp                      	        0x10c2771c2 YGNodeComputeFlexBasisForChildren(YGNode*, float, float, YGMeasureMode, YGMeasureMode, YGDirection, YGFlexDirection, YGConfig*, bool, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 1010 (Yoga.cpp:1930)
20  MyApp                      	        0x10c26e8ce YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 2334 (Yoga.cpp:2859)
21  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
22  MyApp                      	        0x10c27ae11 YGNodeComputeFlexBasisForChild(YGNode*, YGNode*, float, YGMeasureMode, float, float, float, YGMeasureMode, YGDirection, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2865 (Yoga.cpp:1410)
23  MyApp                      	        0x10c2771c2 YGNodeComputeFlexBasisForChildren(YGNode*, float, float, YGMeasureMode, YGMeasureMode, YGDirection, YGFlexDirection, YGConfig*, bool, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 1010 (Yoga.cpp:1930)
24  MyApp                      	        0x10c26e8ce YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 2334 (Yoga.cpp:2859)
25  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
26  MyApp                      	        0x10c2796d5 YGNodeAbsoluteLayoutChild(YGNode*, YGNode*, float, YGMeasureMode, float, YGDirection, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 1781 (Yoga.cpp:1538)
27  MyApp                      	        0x10c271774 YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 14276 (Yoga.cpp:3522)
28  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
29  MyApp                      	        0x10c2797f2 YGNodeAbsoluteLayoutChild(YGNode*, YGNode*, float, YGMeasureMode, float, YGDirection, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2066 (Yoga.cpp:1560)
30  MyApp                      	        0x10c271774 YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 14276 (Yoga.cpp:3522)
31  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
32  MyApp                      	        0x10c26faf1 YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 6977 (Yoga.cpp:3165)
33  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
34  MyApp                      	        0x10c26faf1 YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 6977 (Yoga.cpp:3165)
35  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
36  MyApp                      	        0x10c26faf1 YGNodelayoutImpl(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int, facebook::yoga::LayoutPassReason) + 6977 (Yoga.cpp:3165)
37  MyApp                      	        0x10c26da5c YGLayoutNodeInternal(YGNode*, float, float, YGDirection, YGMeasureMode, YGMeasureMode, float, float, bool, facebook::yoga::LayoutPassReason, YGConfig*, facebook::yoga::LayoutData&, void*, unsigned int, unsigned int) + 2172 (Yoga.cpp:3917)
38  MyApp                      	        0x10c271eda YGNodeCalculateLayoutWithContext + 1178 (Yoga.cpp:4173)
39  MyApp                      	        0x10c272ea3 YGNodeCalculateLayout + 51 (Yoga.cpp:4271)
40  MyApp                      	        0x10bf15b1a -[RCTShadowView layoutWithMinimumSize:maximumSize:layoutDirection:layoutContext:] + 314 (RCTShadowView.m:279)
41  MyApp                      	        0x10bf01690 -[RCTRootShadowView layoutWithAffectedShadowViews:] + 288 (RCTRootShadowView.m:35)
42  MyApp                      	        0x10bd5f9c3 -[REAUIManager uiBlockWithLayoutUpdateForRootView:] + 163 (REAUIManager.mm:163)
43  MyApp                      	        0x10bf3e62a -[RCTUIManager _layoutAndMount] + 442 (RCTUIManager.m:1165)
44  MyApp                      	        0x10bf3e461 -[RCTUIManager batchDidComplete] + 33 (RCTUIManager.m:1148)
45  MyApp                      	        0x10be7b3e7 __32-[RCTCxxBridge batchDidComplete]_block_invoke + 71 (RCTCxxBridge.mm:1573)
46  libdispatch.dylib             	    0x7fff2010532f _dispatch_call_block_and_release + 12
47  libdispatch.dylib             	    0x7fff20106508 _dispatch_client_callout + 8
48  libdispatch.dylib             	    0x7fff2010c3f9 _dispatch_lane_serial_drain + 715
49  libdispatch.dylib             	    0x7fff2010cf74 _dispatch_lane_invoke + 403
50  libdispatch.dylib             	    0x7fff20117577 _dispatch_workloop_worker_thread + 782
51  libsystem_pthread.dylib       	    0x7fff60c96fd0 _pthread_wqthread + 326
52  libsystem_pthread.dylib       	    0x7fff60c95f57 start_wqthread + 15

smikheiev avatar Oct 25 '22 10:10 smikheiev

@smikheiev Yeah it’s the same bug, reanimated holding the main thread makes this code (new to 6.3.3 of date time picker) unsafe:

static YGSize RNDateTimePickerShadowViewMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode)
{
  RNDateTimePickerShadowView *shadowPickerView = (__bridge RNDateTimePickerShadowView *)YGNodeGetContext(node);

  __block CGSize size;
  dispatch_sync(dispatch_get_main_queue(), ^{
    [shadowPickerView.picker setDate:shadowPickerView.date];
    [shadowPickerView.picker setDatePickerMode:shadowPickerView.mode];
    [shadowPickerView.picker setLocale:shadowPickerView.locale];
    if (@available(iOS 14.0, *)) {
      [shadowPickerView.picker setPreferredDatePickerStyle:shadowPickerView.displayIOS];
    }
    size = [shadowPickerView.picker sizeThatFits:UILayoutFittingCompressedSize];
  });

cltnschlosser avatar Oct 25 '22 12:10 cltnschlosser

I got the same issue for using "react-native-reanimated": "1.13.3" & "react-native": "0.64.2". But i didn't found any solution for that. Any update on this issue ?

SandeepKumar213 avatar Dec 12 '22 06:12 SandeepKumar213

Facing the same issue in reanimated v3.0.2. Any help to fix this issue? @cltnschlosser @ajsmth @tomekzaw @EmmanuelSalazarID Did you guys find a solution?

malikzype avatar Mar 20 '23 13:03 malikzype

"react-native-reanimated": "^3.1.0",

same here: 2023-05-10 02:11:32.575475+0200 baby_music[39315:2687260] *** Assertion failure in -REANodesManager uiManager:performMountingWithBlock:, /Users/simo97/Desktop/baby_music/node_modules/react-native-reanimated/ios/REANodesManager.mm:246 2023-05-10 02:11:32.576152+0200 baby_music[39315:2687260] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Mouting block is expected to not be set' *** First throw call stack: (0x1a6776d94 0x19f82c3d0 0x1a0f21808 0x102807534 0x1029bcd94 0x1029b7bcc 0x1029b7928 0x1029b76a4 0x102806a6c 0x102807c18 0x1029bd5c4 0x105f50520 0x105f52038 0x105f5a0b0 0x105f5adf4 0x105f67c74 0x206103ddc 0x206103b7c) (lldb)

Pnlvfx avatar May 10 '23 00:05 Pnlvfx

Facing same issue

sirajtahrawashmen avatar May 23 '23 10:05 sirajtahrawashmen

You can apply this patch, then it works (somewhere is an open PR for this):

react-native-reanimated+3.1.0.patch

diff --git a/node_modules/react-native-reanimated/ios/REANodesManager.mm b/node_modules/react-native-reanimated/ios/REANodesManager.mm
index 26bb253..10e6028 100644
--- a/node_modules/react-native-reanimated/ios/REANodesManager.mm
+++ b/node_modules/react-native-reanimated/ios/REANodesManager.mm
@@ -85,19 +85,77 @@ using namespace facebook::react;
 
 @end
 
-@interface REANodesManager () <RCTUIManagerObserver>
+#ifndef RCT_NEW_ARCH_ENABLED
 
+@interface REASyncUpdateObserver : NSObject <RCTUIManagerObserver>
 @end
 
+@implementation REASyncUpdateObserver {
+  volatile void (^_mounting)(void);
+  volatile BOOL _waitTimedOut;
+  dispatch_semaphore_t _semaphore;
+}
+
+- (instancetype)init
+{
+  self = [super init];
+  if (self) {
+    _mounting = nil;
+    _waitTimedOut = NO;
+    _semaphore = dispatch_semaphore_create(0);
+  }
+  return self;
+}
+
+- (void)dealloc
+{
+  RCTAssert(_mounting == nil, @"Mouting block was set but never executed. This may lead to UI inconsistencies");
+}
+
+- (void)unblockUIThread
+{
+  RCTAssertUIManagerQueue();
+  dispatch_semaphore_signal(_semaphore);
+}
+
+- (void)waitAndMountWithTimeout:(NSTimeInterval)timeout
+{
+  RCTAssertMainQueue();
+  long result = dispatch_semaphore_wait(_semaphore, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC));
+  if (result != 0) {
+    @synchronized(self) {
+      _waitTimedOut = YES;
+    }
+  }
+  if (_mounting) {
+    _mounting();
+    _mounting = nil;
+  }
+}
+
+- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block
+{
+  RCTAssertUIManagerQueue();
+  @synchronized(self) {
+    if (_waitTimedOut) {
+      return NO;
+    } else {
+      _mounting = block;
+      return YES;
+    }
+  }
+}
+
+@end
+
+#endif
+
 @implementation REANodesManager {
   CADisplayLink *_displayLink;
   BOOL _wantRunUpdates;
   NSMutableArray<REAOnAnimationCallback> *_onAnimationCallbacks;
   BOOL _tryRunBatchUpdatesSynchronously;
   REAEventHandler _eventHandler;
-  volatile void (^_mounting)(void);
-  NSObject *_syncLayoutUpdatesWaitLock;
-  volatile BOOL _syncLayoutUpdatesWaitTimedOut;
   NSMutableDictionary<NSNumber *, ComponentUpdate *> *_componentUpdateBuffer;
   NSMutableDictionary<NSNumber *, UIView *> *_viewRegistry;
 #ifdef RCT_NEW_ARCH_ENABLED
@@ -125,7 +183,6 @@ using namespace facebook::react;
     _operationsInBatch = [NSMutableDictionary new];
     _componentUpdateBuffer = [NSMutableDictionary new];
     _viewRegistry = [_uiManager valueForKey:@"_viewRegistry"];
-    _syncLayoutUpdatesWaitLock = [NSObject new];
   }
 
   _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onAnimationFrame:)];
@@ -241,19 +298,6 @@ using namespace facebook::react;
   }
 }
 
-- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block
-{
-  RCTAssert(_mounting == nil, @"Mouting block is expected to not be set");
-  @synchronized(_syncLayoutUpdatesWaitLock) {
-    if (_syncLayoutUpdatesWaitTimedOut) {
-      return NO;
-    } else {
-      _mounting = block;
-      return YES;
-    }
-  }
-}
-
 - (void)performOperations
 {
 #ifdef RCT_NEW_ARCH_ENABLED
@@ -268,8 +312,7 @@ using namespace facebook::react;
     _tryRunBatchUpdatesSynchronously = NO;
 
     __weak __typeof__(self) weakSelf = self;
-    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
-    _syncLayoutUpdatesWaitTimedOut = NO;
+    REASyncUpdateObserver *syncUpdateObserver = [REASyncUpdateObserver new];
     RCTExecuteOnUIManagerQueue(^{
       __typeof__(self) strongSelf = weakSelf;
       if (strongSelf == nil) {
@@ -278,7 +321,7 @@ using namespace facebook::react;
       BOOL canUpdateSynchronously = trySynchronously && ![strongSelf.uiManager hasEnqueuedUICommands];
 
       if (!canUpdateSynchronously) {
-        dispatch_semaphore_signal(semaphore);
+        [syncUpdateObserver unblockUIThread];
       }
 
       for (int i = 0; i < copiedOperationsQueue.count; i++) {
@@ -286,8 +329,8 @@ using namespace facebook::react;
       }
 
       if (canUpdateSynchronously) {
-        [strongSelf.uiManager runSyncUIUpdatesWithObserver:strongSelf];
-        dispatch_semaphore_signal(semaphore);
+        [strongSelf.uiManager runSyncUIUpdatesWithObserver:syncUpdateObserver];
+        [syncUpdateObserver unblockUIThread];
       }
       // In case canUpdateSynchronously=true we still have to send uiManagerWillPerformMounting event
       // to observers because some components (e.g. TextInput) update their UIViews only on that event.
@@ -298,17 +341,7 @@ using namespace facebook::react;
       // from CADisplayLink but it is easier to hardcode it for the time being.
       // The reason why we use frame duration here is that if takes longer than one frame to complete layout tasks
       // there is no point of synchronizing layout with the UI interaction as we get that one frame delay anyways.
-      long result = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC));
-      if (result != 0) {
-        @synchronized(_syncLayoutUpdatesWaitLock) {
-          _syncLayoutUpdatesWaitTimedOut = YES;
-        }
-      }
-    }
-
-    if (_mounting) {
-      _mounting();
-      _mounting = nil;
+      [syncUpdateObserver waitAndMountWithTimeout:0.016];
     }
   }
   _wantRunUpdates = NO;

happyfloat avatar May 23 '23 13:05 happyfloat

Any update on this? If it gets fixed, will it get released on 2.x.x?

bcgilliom avatar Jun 07 '23 20:06 bcgilliom