Fixed deadlock in RCTModuleData
Summary: public Fixed a potential deadlock issue if code attempted to access a module via [bridge moduleForName/Class:] while it was being initialized. Reviewed By: lry Differential Revision: D2807827 fb-gh-sync-id: 58cafe9b92c094dde632d17245fb9b342a0fe9e0
This commit is contained in:
parent
9037d374e1
commit
23cd9febbc
|
@ -333,14 +333,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
|||
|
||||
for (RCTModuleData *moduleData in _moduleDataByID) {
|
||||
if (moduleData.hasInstance) {
|
||||
[moduleData methodQueue]; // initialize the queue
|
||||
}
|
||||
}
|
||||
|
||||
for (RCTModuleData *moduleData in _moduleDataByID) {
|
||||
if (moduleData.hasInstance) {
|
||||
[self registerModuleForFrameUpdates:moduleData.instance
|
||||
withModuleData:moduleData];
|
||||
[moduleData finishSetupForInstance];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,11 +25,18 @@
|
|||
|
||||
/**
|
||||
* Sets the bridge for the module instance. This is only needed when using the
|
||||
* `initWithModuleID:instance:` constructor. Otherwise, the bridge will be set
|
||||
* `initWithModuleInstance:bridge:` constructor. Otherwise, the bridge will be set
|
||||
* automatically when the module is first accessed.
|
||||
*/
|
||||
- (void)setBridgeForInstance;
|
||||
|
||||
/**
|
||||
* Sets the methodQueue and performs the remaining setup for the module. This is
|
||||
* only needed when using the `initWithModuleInstance:bridge:` constructor.
|
||||
* Otherwise it will be done automatically when the module is first accessed.
|
||||
*/
|
||||
- (void)finishSetupForInstance;
|
||||
|
||||
@property (nonatomic, strong, readonly) Class moduleClass;
|
||||
@property (nonatomic, copy, readonly) NSString *name;
|
||||
|
||||
|
|
|
@ -70,6 +70,18 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
|||
}
|
||||
}
|
||||
|
||||
- (void)finishSetupForInstance
|
||||
{
|
||||
if (!_setupComplete) {
|
||||
_setupComplete = YES;
|
||||
[self setUpMethodQueue];
|
||||
[_bridge registerModuleForFrameUpdates:_instance withModuleData:self];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDidInitializeModuleNotification
|
||||
object:_bridge
|
||||
userInfo:@{@"module": _instance}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setUpMethodQueue
|
||||
{
|
||||
if (!_methodQueue) {
|
||||
|
@ -90,19 +102,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
|||
[(id)_instance setValue:_methodQueue forKey:@"methodQueue"];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
RCTLogError(@"%@ is returning nil for it's methodQueue, which is not "
|
||||
RCTLogError(@"%@ is returning nil for its methodQueue, which is not "
|
||||
"permitted. You must either return a pre-initialized "
|
||||
"queue, or @synthesize the methodQueue to let the bridge "
|
||||
"create a queue for you.", self.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Needs to be sent after bridge has been set for all module instances.
|
||||
// Makes sense to put it here, since the same rules apply for methodQueue.
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:RCTDidInitializeModuleNotification
|
||||
object:_bridge userInfo:@{@"module": _instance}];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,11 +130,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
|||
// initialization requires it (View Managers get their queue by calling
|
||||
// self.bridge.uiManager.methodQueue)
|
||||
[self setBridgeForInstance];
|
||||
[self setUpMethodQueue];
|
||||
[_bridge registerModuleForFrameUpdates:_instance withModuleData:self];
|
||||
_setupComplete = YES;
|
||||
}
|
||||
[_instanceLock unlock];
|
||||
|
||||
[self finishSetupForInstance];
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue