Fixed Deadlock

Running this in a detached expo app can sometimes deadlock from thread issues.
I've replaced `dispatch_sync(dispatch_get_main_queue(), ^{});`  with `RCTUnsafeExecuteOnMainQueueSync(^{});` to fix this.

I only hit the error in the `RNFirebaseStorage.m` but it seems like the `RNFirebaseAnalytics.m` and `RNFirebase.m` modules could also have this same issue.

`RCTUnsafeExecuteOnMainQueueSync` checks to see if the method is being executed on the main thread before trying to sync to the main thread. If you try to sync on the main thread whilst on the main thread, you hit a deadlock.

You can read more about it here: https://stackoverflow.com/questions/12379059/why-is-this-dispatch-sync-call-freezing?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

The only testing I did was in a seperate detached ExpoKit project. Running this function would cause the crash.
```js
await firebase
      .storage()
      .ref(uploadUri)
      .putFile(uri);
```
This commit is contained in:
Evan Bacon 2018-06-08 14:44:48 -07:00
parent 2a083f7deb
commit cca3c13d2d
3 changed files with 8 additions and 5 deletions

View File

@ -1,6 +1,7 @@
#import "RNFirebase.h"
#import "RNFirebaseUtil.h"
#import <FirebaseCore/FirebaseCore.h>
#import <React/RCTUtils.h>
@implementation RNFirebase
RCT_EXPORT_MODULE(RNFirebase);
@ -28,7 +29,7 @@ RCT_EXPORT_METHOD(initializeApp:
callback:
(RCTResponseSenderBlock) callback) {
dispatch_sync(dispatch_get_main_queue(), ^{
RCTUnsafeExecuteOnMainQueueSync(^{
FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName];
if (!existingApp) {

View File

@ -1,4 +1,5 @@
#import "RNFirebaseAnalytics.h"
#import <React/RCTUtils.h>
#if __has_include(<FirebaseAnalytics/FIRAnalytics.h>)
#import <FirebaseAnalytics/FIRAnalytics.h>
@ -16,7 +17,7 @@ RCT_EXPORT_METHOD(setAnalyticsCollectionEnabled:(BOOL) enabled) {
}
RCT_EXPORT_METHOD(setCurrentScreen:(NSString *) screenName screenClass:(NSString *) screenClassOverriew) {
dispatch_sync(dispatch_get_main_queue(), ^{
RCTUnsafeExecuteOnMainQueueSync(^{
[FIRAnalytics setScreenName:screenName screenClass:screenClassOverriew];
});
}

View File

@ -7,6 +7,7 @@
#import <MobileCoreServices/MobileCoreServices.h>
#import <Photos/Photos.h>
#import <Firebase.h>
#import <React/RCTUtils.h>
@implementation RNFirebaseStorage
@ -120,7 +121,7 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appDisplayName
NSURL *localFile = [NSURL fileURLWithPath:localPath];
__block FIRStorageDownloadTask *downloadTask;
dispatch_sync(dispatch_get_main_queue(), ^{
RCTUnsafeExecuteOnMainQueueSync(^{
downloadTask = [fileRef writeToFile:localFile];
});
@ -298,7 +299,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
- (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
__block FIRStorageUploadTask *uploadTask;
dispatch_sync(dispatch_get_main_queue(), ^{
RCTUnsafeExecuteOnMainQueueSync(^{
uploadTask = [fileRef putFile:url metadata:firmetadata];
});
[self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];
@ -307,7 +308,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
- (void)uploadData:(NSString *)appDisplayName data:(NSData *)data firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
__block FIRStorageUploadTask *uploadTask;
dispatch_sync(dispatch_get_main_queue(), ^{
RCTUnsafeExecuteOnMainQueueSync(^{
uploadTask = [fileRef putData:data metadata:firmetadata];
});
[self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];