From 44cbec28bdf93ecb90d8a2f4e2c1e5f4888b1ae9 Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Fri, 11 Dec 2015 01:42:17 -0800 Subject: [PATCH] Work around race condition in bridge deallocation Reviewed By: tadeuzagallo, nicklockwood Differential Revision: D2748820 fb-gh-sync-id: 40084ab4bcc606ccbde8b71c2389e602c4dd8e22 --- React/Base/RCTBridge.m | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 3e4a1bc5c..70bd92688 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -36,7 +36,11 @@ NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules"; @interface RCTBridge () -@property (nonatomic, strong) RCTBatchedBridge *batchedBridge; +// This property is mostly used on the main thread, but may be touched from +// a background thread if the RCTBridge happens to deallocate on a background +// thread. Therefore, we want all writes to it to be seen atomically. +@property (atomic, strong) RCTBatchedBridge *batchedBridge; + @property (nonatomic, copy, readonly) RCTBridgeModuleProviderBlock moduleProvider; @end @@ -232,12 +236,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) - (NSArray *)moduleClasses { - return _batchedBridge.moduleClasses; + return self.batchedBridge.moduleClasses; } - (id)moduleForName:(NSString *)moduleName { - return [_batchedBridge moduleForName:moduleName]; + return [self.batchedBridge moduleForName:moduleName]; } - (id)moduleForClass:(Class)moduleClass @@ -270,30 +274,34 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) // Sanitize the bundle URL _bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString]; - _batchedBridge = [[RCTBatchedBridge alloc] initWithParentBridge:self]; + self.batchedBridge = [[RCTBatchedBridge alloc] initWithParentBridge:self]; } - (BOOL)isLoading { - return _batchedBridge.loading; + return self.batchedBridge.loading; } - (BOOL)isValid { - return _batchedBridge.valid; + return self.batchedBridge.valid; } - (void)invalidate { - RCTAssertMainThread(); + RCTBatchedBridge *batchedBridge = self.batchedBridge; + self.batchedBridge = nil; - [_batchedBridge invalidate]; - _batchedBridge = nil; + if (batchedBridge) { + RCTExecuteOnMainThread(^{ + [batchedBridge invalidate]; + }, NO); + } } - (void)logMessage:(NSString *)message level:(NSString *)level { - [_batchedBridge logMessage:message level:level]; + [self.batchedBridge logMessage:message level:level]; } @@ -321,7 +329,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) - (NSDictionary *)modules { - return _batchedBridge.modules; + return self.batchedBridge.modules; } @end