From c0692ab0636ccd84fd56ef47f74da0c66cfb1bf5 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Thu, 30 May 2024 11:42:22 -0700 Subject: [PATCH] Re-land: Fix race condition in native module invalidation (#44727) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44727 This is a re-land of https://github.com/facebook/react-native/pull/44048 Reverting it caused even bigger regression, so my earlier assessment was wrong. The initial regression was caused by something else. Changelog: [Internal] - Let's keep the changelog entry form the original diff. Reviewed By: fkgozali Differential Revision: D57970133 fbshipit-source-id: c683d661a805d44434f5491e89dd4b7218379bee --- .../ios/ReactCommon/RCTTurboModuleManager.mm | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm index 648df4b43aa..7354f6bc54f 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm @@ -181,6 +181,11 @@ static Class getFallbackClassFromName(const char *name) return moduleClass; } +typedef struct { + id module; + dispatch_queue_t methodQueue; +} ModuleQueuePair; + @implementation RCTTurboModuleManager { std::shared_ptr _jsInvoker; __weak id _delegate; @@ -1046,7 +1051,7 @@ static Class getFallbackClassFromName(const char *name) { // Backward-compatibility: RCTInvalidating handling. dispatch_group_t moduleInvalidationGroup = dispatch_group_create(); - + std::vector modulesToInvalidate; for (auto &pair : _moduleHolders) { std::string moduleName = pair.first; ModuleHolder *moduleHolder = &pair.second; @@ -1069,22 +1074,31 @@ static Class getFallbackClassFromName(const char *name) [module class]); continue; } + modulesToInvalidate.push_back({module, methodQueue}); + } + } - dispatch_group_enter(moduleInvalidationGroup); - dispatch_block_t invalidateModule = ^{ - [((id)module) invalidate]; - dispatch_group_leave(moduleInvalidationGroup); - }; + for (auto unused : modulesToInvalidate) { + dispatch_group_enter(moduleInvalidationGroup); + } - if (_bridge) { - [_bridge dispatchBlock:invalidateModule queue:methodQueue]; + for (auto &moduleQueuePair : modulesToInvalidate) { + id module = moduleQueuePair.module; + dispatch_queue_t methodQueue = moduleQueuePair.methodQueue; + + dispatch_block_t invalidateModule = ^{ + [((id)module) invalidate]; + dispatch_group_leave(moduleInvalidationGroup); + }; + + if (_bridge) { + [_bridge dispatchBlock:invalidateModule queue:methodQueue]; + } else { + // Bridgeless mode + if (methodQueue == RCTJSThread) { + invalidateModule(); } else { - // Bridgeless mode - if (methodQueue == RCTJSThread) { - invalidateModule(); - } else { - dispatch_async(methodQueue, invalidateModule); - } + dispatch_async(methodQueue, invalidateModule); } } }