Fixes race condition of Network module (#25156)

Summary:
There exists race condition in `sendRequest:withDelegate:` method, it can do the session creation multiple times, because we don't lock that, which would leads `EXC_BAD_ACCESS` because use and deallocated session concurrently, we can refer to how to create a singleton safely.

Related https://github.com/facebook/react-native/issues/25152.

## Changelog

[iOS] [Fixed] - Fixes race condition of Network module
Pull Request resolved: https://github.com/facebook/react-native/pull/25156

Differential Revision: D15671734

Pulled By: sammy-SC

fbshipit-source-id: 5021e6cf33c2b55e3f7adf573ab5c8e6a8d82e23
This commit is contained in:
zhongwuzw 2019-06-06 04:04:59 -07:00 коммит произвёл Facebook Github Bot
Родитель 67e589ce06
Коммит 831f5fe210
1 изменённых файлов: 7 добавлений и 13 удалений

Просмотреть файл

@ -29,12 +29,12 @@ RCT_EXPORT_MODULE()
- (void)invalidate
{
dispatch_async(self->_methodQueue, ^{
std::lock_guard<std::mutex> lock(_mutex);
[self->_session invalidateAndCancel];
self->_session = nil;
});
}
// Needs to lock before call this method.
- (BOOL)isValid
{
// if session == nil and delegates != nil, we've been invalidated
@ -58,6 +58,7 @@ RCT_EXPORT_MODULE()
- (NSURLSessionDataTask *)sendRequest:(NSURLRequest *)request
withDelegate:(id<RCTURLRequestDelegate>)delegate
{
std::lock_guard<std::mutex> lock(_mutex);
// Lazy setup
if (!_session && [self isValid]) {
// You can override default NSURLSession instance property allowsCellularAccess (default value YES)
@ -83,19 +84,12 @@ RCT_EXPORT_MODULE()
delegate:self
delegateQueue:callbackQueue];
std::lock_guard<std::mutex> lock(_mutex);
_delegates = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory
valueOptions:NSPointerFunctionsStrongMemory
capacity:0];
}
__block NSURLSessionDataTask *task = nil;
dispatch_sync(self->_methodQueue, ^{
task = [self->_session dataTaskWithRequest:request];
});
{
std::lock_guard<std::mutex> lock(_mutex);
NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
[_delegates setObject:delegate forKey:task];
}
[task resume];
return task;
}