From 6b104bbe015c93a40a73232fdb92a99e3799b7ac Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Fri, 23 Aug 2024 08:08:58 -0700 Subject: [PATCH] Fixes race condition when setup image loader (#46153) Summary: Fixes https://github.com/facebook/react-native/issues/46115 . ## Changelog: [IOS] [FIXED] - Fixes race condition when setup image loader Pull Request resolved: https://github.com/facebook/react-native/pull/46153 Test Plan: crash in https://github.com/facebook/react-native/issues/46115 Reviewed By: cipolleschi Differential Revision: D61662905 Pulled By: andrewdacenko fbshipit-source-id: 22bc45b473c7c8e1c811e41f5030220ca7988e1f --- .../Libraries/Image/RCTImageLoader.mm | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/react-native/Libraries/Image/RCTImageLoader.mm b/packages/react-native/Libraries/Image/RCTImageLoader.mm index d6db050e35c36e..68a12d351227ef 100644 --- a/packages/react-native/Libraries/Image/RCTImageLoader.mm +++ b/packages/react-native/Libraries/Image/RCTImageLoader.mm @@ -68,6 +68,8 @@ - (void)setReactDecodedImageBytes:(NSInteger)bytes @end @implementation RCTImageLoader { + std::atomic _isLoaderSetup; + std::mutex _loaderSetupLock; NSArray> * (^_loadersProvider)(RCTModuleRegistry *); NSArray> * (^_decodersProvider)(RCTModuleRegistry *); NSArray> *_loaders; @@ -106,6 +108,7 @@ - (instancetype)initWithRedirectDelegate:(id)redirectD { if (self = [super init]) { _redirectDelegate = redirectDelegate; + _isLoaderSetup = NO; } return self; } @@ -123,12 +126,16 @@ - (instancetype)initWithRedirectDelegate:(id)redirectD - (void)setUp { - // Set defaults - _maxConcurrentLoadingTasks = _maxConcurrentLoadingTasks ?: 4; - _maxConcurrentDecodingTasks = _maxConcurrentDecodingTasks ?: 2; - _maxConcurrentDecodingBytes = _maxConcurrentDecodingBytes ?: 30 * 1024 * 1024; // 30MB - - _URLRequestQueue = dispatch_queue_create("com.facebook.react.ImageLoaderURLRequestQueue", DISPATCH_QUEUE_SERIAL); + std::lock_guard guard(_loaderSetupLock); + if (!_isLoaderSetup) { + // Set defaults + _maxConcurrentLoadingTasks = _maxConcurrentLoadingTasks ?: 4; + _maxConcurrentDecodingTasks = _maxConcurrentDecodingTasks ?: 2; + _maxConcurrentDecodingBytes = _maxConcurrentDecodingBytes ?: 30 * 1024 * 1024; // 30MB + + _URLRequestQueue = dispatch_queue_create("com.facebook.react.ImageLoaderURLRequestQueue", DISPATCH_QUEUE_SERIAL); + _isLoaderSetup = YES; + } } - (float)handlerPriority @@ -156,7 +163,7 @@ - (void)setImageCache:(id)cache - (id)imageURLLoaderForURL:(NSURL *)URL { - if (!_maxConcurrentLoadingTasks) { + if (!_isLoaderSetup) { [self setUp]; } @@ -229,7 +236,7 @@ - (void)setImageCache:(id)cache - (id)imageDataDecoderForData:(NSData *)data { - if (!_maxConcurrentLoadingTasks) { + if (!_isLoaderSetup) { [self setUp]; } @@ -564,7 +571,7 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req } // All access to URL cache must be serialized - if (!_URLRequestQueue) { + if (!_isLoaderSetup) { [self setUp]; } @@ -979,7 +986,7 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)data }); }; - if (!_URLRequestQueue) { + if (!_isLoaderSetup) { [self setUp]; } dispatch_async(_URLRequestQueue, ^{