Corner case crashes in RCTImageLoader and RCTNetworkTask
See original GitHub issueDescription
We have several crashes from RCTImageLoader
and RCTNetworkTask
, actually I think those from RCTNetworkTask
are also those tasks from RCTImageLoader
.
Most of the stack trees may be useless, but those are the top ones:
Crashed: com.facebook.react.NetworkingQueue
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x00000003bd0fbec8
0 libobjc.A.dylib objc_object::release() + 8
1 libsystem_blocks.dylib _Block_release + 160
...
9 libsystem_pthread.dylib start_wqthread + 4
Crashed: NSOperationQueue 0x1702244a0 :: NSOperation 0x174852ed0 (QOS: USER_INITIATED)
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x00000000dbbabec8
0 libobjc.A.dylib objc_object::release() + 8
1 React RCTNetworkTask.m line 183 -[RCTNetworkTask URLRequest:didReceiveData:]
2 React RCTFileRequestHandler.m line 77 __50-[RCTFileRequestHandler sendRequest:withDelegate:]_block_invoke
3 Foundation __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16
...
13 libsystem_pthread.dylib start_wqthread + 4
Crashed: com.facebook.react.NetworkingQueue
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x00000004d710bec8
0 libobjc.A.dylib objc_retain + 16
1 React RCTImageLoader.m line 482 __64-[RCTImageLoader _loadURLRequest:progressBlock:completionBlock:]_block_invoke.227
2 libdispatch.dylib _dispatch_call_block_and_release + 24
...
10 libsystem_pthread.dylib start_wqthread + 4
Crashed: NSOperationQueue 0x170426d40 :: NSOperation 0x170a57190 (QOS: USER_INITIATED)
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x00000004f636bec8
0 libobjc.A.dylib objc_retain + 16
1 React RCTNetworkTask.m line 180 -[RCTNetworkTask URLRequest:didReceiveData:]
2 React RCTFileRequestHandler.m line 77 __50-[RCTFileRequestHandler sendRequest:withDelegate:]_block_invoke
3 Foundation __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16
...
13 libsystem_pthread.dylib start_wqthread + 4
Reproduction Steps
I’ve tried for several weeks but it’s hard to reproduce, but here’re some of my thoughts:
-
When our client received a hot patch from server, we’ll setup a new
RCTBridge
using new bundle, so the global shared bridge is pointing to the new bridge, and the old one will dealloc once there’s no view holding it. -
I’m not sure about the order of dealloc (destruction) of those modules and the method queue they’re holding.
-
I noticed
RCTImageLoader
is actually usingRCTNetworking
module to load images, the callback ofRCTNetworking
is executed on its own method queue. -
So when the
RCTNetworkTask
try to retain something from the queue ofRCTImageLoader
but actually it’s been deallocated, it crashes.
I guess so because as you can see, one crash from RCTImageLoader
happens on this line https://github.com/facebook/react-native/blob/v0.44.0/Libraries/Image/RCTImageLoader.m#L482 in thread com.facebook.react.NetworkingQueue
.
Sample Code
Sorry but there’s no special sample code to provide.
Solution
Is it possible to have a standalone global networking manager and image manager, instead of belonging to a bridge? Thus, when you have multiple bridges, or when you’re deallocating one bridge, the networking queues are not deallocated, to prevent the crashes.
Also, although it’s rare to have multiple RN bridges in one app, but sharing networking component may help on memory usage when you do have multiple bridges.
Btw, anyone knows if there’s any fully tested, stable library to use AFNetworking as the networking layer of RN? I’ve found some node modules but seems it’s already dead.
Additional Information
- React Native version: 0.44.0
- Platform: iOS
- Development Operating System: macOS
- Build tools: Xcode 8.3.3
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:5
Top GitHub Comments
I’m also seeing these crashes when using
Image.prefetch
. They occur intermittently, but regularly on our CI."react-native": "0.42.3"
FYI, we forked and rewrote
RCTImageLoader
to useSDWebImage
to load images, instead ofRCTNetworking
.