Skip to content

Commit

Permalink
Invalidate TurboModules on their method queues
Browse files Browse the repository at this point in the history
Summary:
## Rationale
With the bridge, the invalidate method of every TurboModule gets called on the TurboModule's method queue. This ensures that we can safely clean up resources accessed in the TurboModule's async methods. In bridgeless mode, we don't invalidate each module on its method queue. After this diff, we will clean up every TurboModule on its own method queue.

## Changes
- Make RCTInstance dealloc itself on the JavaScript thread.
- Terminate the JavaScript thread on the JavaScript thread. This ensures that no work executes on the JavaScript thread after we clean up RCTInstance.
- Make [RCTTurboModuleManager invalidate] execute right before RCTInstance terminates the JavaScript thread.
- **Fix:** Make [RCTTurboModuleManger invalidate] synchronously invalidate modules on their own method queues.

Changelog: [Internal]

Reviewed By: PeteTheHeat

Differential Revision: D27933587

fbshipit-source-id: 7630e7fc074df2f5a3293192431105c747b8588f
  • Loading branch information
RSNara authored and facebook-github-bot committed Apr 23, 2021
1 parent 090196f commit f34a289
Showing 1 changed file with 39 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,27 @@ - (void)bridgeWillInvalidateModules:(NSNotification *)notification
return;
}

[self _enterInvalidatingState];
}

- (void)bridgeDidInvalidateModules:(NSNotification *)notification
{
RCTBridge *bridge = notification.userInfo[@"bridge"];
if (bridge != _bridge) {
return;
}

[self _invalidateModules];
}

- (void)invalidate
{
[self _enterInvalidatingState];
[self _invalidateModules];
}

- (void)_enterInvalidatingState
{
// This should halt all insertions into _turboModuleHolders
if (RCTTurboModuleSharedMutexInitEnabled()) {
std::unique_lock<std::shared_timed_mutex> guard(_turboModuleHoldersSharedMutex);
Expand All @@ -844,13 +865,8 @@ - (void)bridgeWillInvalidateModules:(NSNotification *)notification
}
}

- (void)bridgeDidInvalidateModules:(NSNotification *)notification
- (void)_invalidateModules
{
RCTBridge *bridge = notification.userInfo[@"bridge"];
if (bridge != _bridge) {
return;
}

// Backward-compatibility: RCTInvalidating handling.
dispatch_group_t moduleInvalidationGroup = dispatch_group_create();

Expand All @@ -870,17 +886,28 @@ - (void)bridgeDidInvalidateModules:(NSNotification *)notification
if ([module respondsToSelector:@selector(invalidate)]) {
if ([module respondsToSelector:@selector(methodQueue)]) {
dispatch_queue_t methodQueue = [module performSelector:@selector(methodQueue)];

if (methodQueue) {
dispatch_group_enter(moduleInvalidationGroup);
[bridge
dispatchBlock:^{
[((id<RCTInvalidating>)module) invalidate];
dispatch_group_leave(moduleInvalidationGroup);
}
queue: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 {
dispatch_async(methodQueue, invalidateModule);
}
}
continue;
}
}

[((id<RCTInvalidating>)module) invalidate];
}
}
Expand All @@ -893,26 +920,4 @@ - (void)bridgeDidInvalidateModules:(NSNotification *)notification
_turboModuleCache.clear();
}

- (void)invalidate
{
if (RCTTurboModuleSharedMutexInitEnabled()) {
std::unique_lock<std::shared_timed_mutex> guard(_turboModuleHoldersSharedMutex);
_invalidating = true;
} else {
std::lock_guard<std::mutex> guard(_turboModuleHoldersMutex);
_invalidating = true;
}

// Backward-compatibility: RCTInvalidating handling, but not adhering to desired methodQueue.
for (const auto &p : _turboModuleHolders) {
id<RCTTurboModule> module = p.second.getModule();
if ([module respondsToSelector:@selector(invalidate)]) {
[((id<RCTInvalidating>)module) invalidate];
}
}

_turboModuleHolders.clear();
_turboModuleCache.clear();
}

@end

0 comments on commit f34a289

Please sign in to comment.