mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Conditionally disable TurboModuleManager delegate locking
Summary: ## Context Whenever the TurboModuleManager calls into its delegate, it [acquires a lock](https://www.internalfb.com/code/fbsource/[f14548634e72009989c844a2ef025915ef74159e]/xplat/js/react-native-github/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm?lines=429%2C513). We initially introduced this mutex (in D21170099 (https://github.com/facebook/react-native/commit/2c473e1a38c35957fe80b6c334a1983c034c2bbc)). It serializes access to the TurboModuleManager delegate during TurboModule create. ## Problems - When we call into the delegate, we acquire a lock, and call into arbitrary product code: getModuleClassFromName, getModuleInstanceFromClass. If any of these two product methods create another TurboModule, the application will deadlock, because we'll acquire the same std::mutex twice. ## Fix The delegate methods of TurboModuleManager are usually implemented as [switch cases over the NativeModule names or NativeModule classes](https://www.internalfb.com/code/fbsource/[f015e461de4e7a18d0d52a697a53086fe6a3b91c]/fbobjc/Apps/Wilde/FBReactModule2/FBReactModuleAPI/FBReactModuleAPI/Exported/FBReactModule.mm?lines=1481-1488%2C1490-1537%2C1539-1577). So, it should be safe to call into them concurrently for two different modules. So, while we could fix the problem by migrating the TurboModuleManager to an std::recursive_mutex, one could make an argument that this locking shouldn't even be necessary in the first place. We don't have this locking in the Android TurboModule system. ## Changes This diff introduces a flag in React Native that allows to to safely remove this TurboModuleManager delegate locking in production. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D30754875 fbshipit-source-id: d04a831c18a2a8b46e9bc07ddf690d8e4d0be8e0
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7243517481
commit
e36bfef0f1
@@ -160,6 +160,10 @@ RCT_EXTERN void RCTEnableTurboModuleEagerInit(BOOL enabled);
|
||||
RCT_EXTERN BOOL RCTTurboModuleSharedMutexInitEnabled(void);
|
||||
RCT_EXTERN void RCTEnableTurboModuleSharedMutexInit(BOOL enabled);
|
||||
|
||||
// Turn off TurboModule delegate locking
|
||||
RCT_EXTERN BOOL RCTTurboModuleManagerDelegateLockingDisabled(void);
|
||||
RCT_EXTERN void RCTDisableTurboModuleManagerDelegateLocking(BOOL enabled);
|
||||
|
||||
typedef enum {
|
||||
kRCTGlobalScope,
|
||||
kRCTGlobalScopeUsingRetainJSCallback,
|
||||
|
||||
@@ -149,6 +149,18 @@ void RCTSetTurboModuleCleanupMode(RCTTurboModuleCleanupMode mode)
|
||||
turboModuleCleanupMode = mode;
|
||||
}
|
||||
|
||||
// Turn off TurboModule delegate locking
|
||||
static BOOL turboModuleManagerDelegateLockingDisabled = NO;
|
||||
BOOL RCTTurboModuleManagerDelegateLockingDisabled(void)
|
||||
{
|
||||
return turboModuleManagerDelegateLockingDisabled;
|
||||
}
|
||||
|
||||
void RCTDisableTurboModuleManagerDelegateLocking(BOOL disabled)
|
||||
{
|
||||
turboModuleManagerDelegateLockingDisabled = disabled;
|
||||
}
|
||||
|
||||
@interface RCTBridge () <RCTReloadListener>
|
||||
@end
|
||||
|
||||
|
||||
@@ -422,9 +422,12 @@ static Class getFallbackClassFromName(const char *name)
|
||||
*/
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(getModuleClassFromName:)]) {
|
||||
std::lock_guard<std::mutex> delegateGuard(_turboModuleManagerDelegateMutex);
|
||||
|
||||
moduleClass = [_delegate getModuleClassFromName:moduleName];
|
||||
if (RCTTurboModuleManagerDelegateLockingDisabled()) {
|
||||
moduleClass = [_delegate getModuleClassFromName:moduleName];
|
||||
} else {
|
||||
std::lock_guard<std::mutex> delegateGuard(_turboModuleManagerDelegateMutex);
|
||||
moduleClass = [_delegate getModuleClassFromName:moduleName];
|
||||
}
|
||||
}
|
||||
|
||||
if (!moduleClass) {
|
||||
@@ -506,9 +509,12 @@ static Class getFallbackClassFromName(const char *name)
|
||||
|
||||
TurboModulePerfLogger::moduleCreateConstructStart(moduleName, moduleId);
|
||||
if ([_delegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) {
|
||||
std::lock_guard<std::mutex> delegateGuard(_turboModuleManagerDelegateMutex);
|
||||
|
||||
module = [_delegate getModuleInstanceFromClass:moduleClass];
|
||||
if (RCTTurboModuleManagerDelegateLockingDisabled()) {
|
||||
module = [_delegate getModuleInstanceFromClass:moduleClass];
|
||||
} else {
|
||||
std::lock_guard<std::mutex> delegateGuard(_turboModuleManagerDelegateMutex);
|
||||
module = [_delegate getModuleInstanceFromClass:moduleClass];
|
||||
}
|
||||
} else {
|
||||
module = [moduleClass new];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user