mirror of
https://github.com/status-im/react-native.git
synced 2025-02-22 22:28:09 +00:00
Added locking around RN bridge cxx module registry to avoid crash
Summary: D12904277 was my sad, optimistic attempt to fix this crash. As @[100006577537606:Slobodan] mentioned on T35879909, the real issue is that moduleRegistry is being created (using _moduleDataByID dict) concurrently while we try to append to this dict. I added locks around these usage of _moduleDataByID. Reviewed By: fkgozali Differential Revision: D12911108 fbshipit-source-id: 2435b7a477c27585898f351c4a0d4c1bd4056756
This commit is contained in:
parent
2486d12b81
commit
1c3191992a
@ -155,6 +155,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||||||
{
|
{
|
||||||
BOOL _wasBatchActive;
|
BOOL _wasBatchActive;
|
||||||
BOOL _didInvalidate;
|
BOOL _didInvalidate;
|
||||||
|
BOOL _moduleRegistryCreated;
|
||||||
|
|
||||||
NSMutableArray<RCTPendingCall> *_pendingCalls;
|
NSMutableArray<RCTPendingCall> *_pendingCalls;
|
||||||
std::atomic<NSInteger> _pendingCount;
|
std::atomic<NSInteger> _pendingCount;
|
||||||
@ -169,6 +170,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||||||
// JS thread management
|
// JS thread management
|
||||||
NSThread *_jsThread;
|
NSThread *_jsThread;
|
||||||
std::shared_ptr<RCTMessageThread> _jsMessageThread;
|
std::shared_ptr<RCTMessageThread> _jsMessageThread;
|
||||||
|
std::mutex _moduleRegistryLock;
|
||||||
|
|
||||||
// This is uniquely owned, but weak_ptr is used.
|
// This is uniquely owned, but weak_ptr is used.
|
||||||
std::shared_ptr<Instance> _reactInstance;
|
std::shared_ptr<Instance> _reactInstance;
|
||||||
@ -209,9 +211,9 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||||||
*/
|
*/
|
||||||
_valid = YES;
|
_valid = YES;
|
||||||
_loading = YES;
|
_loading = YES;
|
||||||
|
_moduleRegistryCreated = NO;
|
||||||
_pendingCalls = [NSMutableArray new];
|
_pendingCalls = [NSMutableArray new];
|
||||||
_displayLink = [RCTDisplayLink new];
|
_displayLink = [RCTDisplayLink new];
|
||||||
|
|
||||||
_moduleDataByName = [NSMutableDictionary new];
|
_moduleDataByName = [NSMutableDictionary new];
|
||||||
_moduleClassesByID = [NSMutableArray new];
|
_moduleClassesByID = [NSMutableArray new];
|
||||||
_moduleDataByID = [NSMutableArray new];
|
_moduleDataByID = [NSMutableArray new];
|
||||||
@ -442,7 +444,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||||||
return _moduleDataByName[RCTBridgeModuleNameForClass(moduleClass)].hasInstance;
|
return _moduleDataByName[RCTBridgeModuleNameForClass(moduleClass)].hasInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (std::shared_ptr<ModuleRegistry>)_buildModuleRegistry
|
- (std::shared_ptr<ModuleRegistry>)_buildModuleRegistryUnlocked
|
||||||
{
|
{
|
||||||
if (!self.valid) {
|
if (!self.valid) {
|
||||||
return {};
|
return {};
|
||||||
@ -489,12 +491,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||||||
executorFactory = std::make_shared<GetDescAdapter>(self, executorFactory);
|
executorFactory = std::make_shared<GetDescAdapter>(self, executorFactory);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is async, but any calls into JS are blocked by the m_syncReady CV in Instance
|
[self _initializeBridgeLocked:executorFactory];
|
||||||
_reactInstance->initializeBridge(
|
|
||||||
std::make_unique<RCTInstanceCallback>(self),
|
|
||||||
executorFactory,
|
|
||||||
_jsMessageThread,
|
|
||||||
[self _buildModuleRegistry]);
|
|
||||||
|
|
||||||
#if RCT_PROFILE
|
#if RCT_PROFILE
|
||||||
if (RCTProfileIsProfiling()) {
|
if (RCTProfileIsProfiling()) {
|
||||||
@ -508,6 +505,19 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||||||
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
|
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)_initializeBridgeLocked:(std::shared_ptr<JSExecutorFactory>)executorFactory
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(_moduleRegistryLock);
|
||||||
|
|
||||||
|
// This is async, but any calls into JS are blocked by the m_syncReady CV in Instance
|
||||||
|
_reactInstance->initializeBridge(
|
||||||
|
std::make_unique<RCTInstanceCallback>(self),
|
||||||
|
executorFactory,
|
||||||
|
_jsMessageThread,
|
||||||
|
[self _buildModuleRegistryUnlocked]);
|
||||||
|
_moduleRegistryCreated = YES;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray<RCTModuleData *> *)registerModulesForClasses:(NSArray<Class> *)moduleClasses
|
- (NSArray<RCTModuleData *> *)registerModulesForClasses:(NSArray<Class> *)moduleClasses
|
||||||
{
|
{
|
||||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways,
|
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways,
|
||||||
@ -706,11 +716,13 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||||||
|
|
||||||
- (void)registerAdditionalModuleClasses:(NSArray<Class> *)modules
|
- (void)registerAdditionalModuleClasses:(NSArray<Class> *)modules
|
||||||
{
|
{
|
||||||
@synchronized (self) {
|
std::lock_guard<std::mutex> guard(_moduleRegistryLock);
|
||||||
|
if (_moduleRegistryCreated) {
|
||||||
NSArray<RCTModuleData *> *newModules = [self _initializeModules:modules withDispatchGroup:NULL lazilyDiscovered:YES];
|
NSArray<RCTModuleData *> *newModules = [self _initializeModules:modules withDispatchGroup:NULL lazilyDiscovered:YES];
|
||||||
if (_reactInstance) {
|
assert(_reactInstance); // at this point you must have reactInstance as you already called reactInstance->initialzeBridge
|
||||||
_reactInstance->getModuleRegistry().registerModules(createNativeModules(newModules, self, _reactInstance));
|
_reactInstance->getModuleRegistry().registerModules(createNativeModules(newModules, self, _reactInstance));
|
||||||
}
|
} else {
|
||||||
|
[self registerModulesForClasses:modules];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user