[ReactNative] Fix racing conditions on reload
Summary: @public That was eventually being released before all the queues had been cleared. Update it so the each modules' queue is immediately invalidated after sending the `-invalidate` message to it, and introduce an intentional retain cycle so the bridge is only released together with all modules, when all the messages have been dispatched. Test Plan: Launch the UIExplorer, and reload it, like, a lot.
This commit is contained in:
parent
2cb0546d15
commit
9228873fb4
|
@ -1042,11 +1042,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
|
||||||
|
|
||||||
- (NSDictionary *)modules
|
- (NSDictionary *)modules
|
||||||
{
|
{
|
||||||
if (!self.isValid) {
|
RCTAssert(!self.isValid || _modulesByName != nil, @"Bridge modules have not yet been initialized. "
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
RCTAssert(_modulesByName != nil, @"Bridge modules have not yet been initialized. "
|
|
||||||
"You may be trying to access a module too early in the startup procedure.");
|
"You may be trying to access a module too early in the startup procedure.");
|
||||||
|
|
||||||
return _modulesByName;
|
return _modulesByName;
|
||||||
|
@ -1074,19 +1070,21 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
|
||||||
_mainDisplayLink = nil;
|
_mainDisplayLink = nil;
|
||||||
|
|
||||||
// Invalidate modules
|
// Invalidate modules
|
||||||
|
dispatch_group_t group = dispatch_group_create();
|
||||||
for (id target in _modulesByID.allObjects) {
|
for (id target in _modulesByID.allObjects) {
|
||||||
if ([target respondsToSelector:@selector(invalidate)]) {
|
if ([target respondsToSelector:@selector(invalidate)]) {
|
||||||
[self dispatchBlock:^{
|
[self dispatchBlock:^{
|
||||||
[(id<RCTInvalidating>)target invalidate];
|
[(id<RCTInvalidating>)target invalidate];
|
||||||
} forModule:target];
|
} forModule:target dispatchGroup:group];
|
||||||
}
|
}
|
||||||
|
_queuesByID[RCTModuleIDsByName[RCTBridgeModuleNameForClass([target class])]] = nil;
|
||||||
}
|
}
|
||||||
|
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
|
||||||
// Release modules (breaks retain cycle if module has strong bridge reference)
|
_queuesByID = nil;
|
||||||
_frameUpdateObservers = nil;
|
_modulesByID = nil;
|
||||||
_modulesByID = nil;
|
_modulesByName = nil;
|
||||||
_queuesByID = nil;
|
_frameUpdateObservers = nil;
|
||||||
_modulesByName = nil;
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!_javaScriptExecutor) {
|
if (!_javaScriptExecutor) {
|
||||||
|
@ -1185,13 +1183,30 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Payload Generation
|
#pragma mark - Payload Generation
|
||||||
|
- (void)dispatchBlock:(dispatch_block_t)block
|
||||||
- (void)dispatchBlock:(dispatch_block_t)block forModule:(id<RCTBridgeModule>)module
|
forModule:(id<RCTBridgeModule>)module
|
||||||
{
|
{
|
||||||
[self dispatchBlock:block forModuleID:RCTModuleIDsByName[RCTBridgeModuleNameForClass([module class])]];
|
[self dispatchBlock:block forModule:module dispatchGroup:NULL];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dispatchBlock:(dispatch_block_t)block forModuleID:(NSNumber *)moduleID
|
- (void)dispatchBlock:(dispatch_block_t)block
|
||||||
|
forModule:(id<RCTBridgeModule>)module
|
||||||
|
dispatchGroup:(dispatch_group_t)group
|
||||||
|
{
|
||||||
|
[self dispatchBlock:block
|
||||||
|
forModuleID:RCTModuleIDsByName[RCTBridgeModuleNameForClass([module class])]
|
||||||
|
dispatchGroup:group];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dispatchBlock:(dispatch_block_t)block
|
||||||
|
forModuleID:(NSNumber *)moduleID
|
||||||
|
{
|
||||||
|
[self dispatchBlock:block forModuleID:moduleID dispatchGroup:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dispatchBlock:(dispatch_block_t)block
|
||||||
|
forModuleID:(NSNumber *)moduleID
|
||||||
|
dispatchGroup:(dispatch_group_t)group
|
||||||
{
|
{
|
||||||
RCTAssertJSThread();
|
RCTAssertJSThread();
|
||||||
|
|
||||||
|
@ -1203,7 +1218,11 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
|
||||||
if (queue == RCTJSThread) {
|
if (queue == RCTJSThread) {
|
||||||
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
|
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
|
||||||
} else if (queue) {
|
} else if (queue) {
|
||||||
dispatch_async(queue, block);
|
if (group != NULL) {
|
||||||
|
dispatch_group_async(group, queue, block);
|
||||||
|
} else {
|
||||||
|
dispatch_async(queue, block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue