Skip to content

Commit

Permalink
Re-land: Fix race condition in native module invalidation (facebook#4…
Browse files Browse the repository at this point in the history
…4727)

Summary:

This is a re-land of facebook#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.

Differential Revision: D57970133
  • Loading branch information
dmytrorykun authored and facebook-github-bot committed May 30, 2024
1 parent 3b59b27 commit abb5c48
Showing 1 changed file with 28 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ static Class getFallbackClassFromName(const char *name)
return moduleClass;
}

typedef struct {
id<RCTBridgeModule> module;
dispatch_queue_t methodQueue;
} ModuleQueuePair;

@implementation RCTTurboModuleManager {
std::shared_ptr<CallInvoker> _jsInvoker;
__weak id<RCTTurboModuleManagerDelegate> _delegate;
Expand Down Expand Up @@ -1046,7 +1051,7 @@ - (void)_invalidateModules
{
// Backward-compatibility: RCTInvalidating handling.
dispatch_group_t moduleInvalidationGroup = dispatch_group_create();

std::vector<ModuleQueuePair> modulesToInvalidate;
for (auto &pair : _moduleHolders) {
std::string moduleName = pair.first;
ModuleHolder *moduleHolder = &pair.second;
Expand All @@ -1069,22 +1074,31 @@ - (void)_invalidateModules
[module class]);
continue;
}
modulesToInvalidate.push_back({module, methodQueue});
}
}

dispatch_group_enter(moduleInvalidationGroup);
dispatch_block_t invalidateModule = ^{
[((id<RCTInvalidating>)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<RCTBridgeModule> module = moduleQueuePair.module;
dispatch_queue_t methodQueue = moduleQueuePair.methodQueue;

dispatch_block_t invalidateModule = ^{
[((id<RCTInvalidating>)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);
}
}
}
Expand Down

0 comments on commit abb5c48

Please sign in to comment.