react-native-document-picker: [iOS] Crashed: com.apple.main-thread

I got this crash today via Crashlytics. It seems we must to handle the code in didPickDocumentsAtURLs on main thread.

Crashed: com.apple.main-thread
0  Stuneo                         0x1050e13b0 -[RNDocumentPicker documentPicker:didPickDocumentsAtURLs:] + 167 (RNDocumentPicker.m:167)
1  UIKitCore                      0x1a03f3384 __74-[UIDocumentPickerViewController _callDelegateWithSelectedURLsAndDismiss:]_block_invoke + 128
2  UIKitCore                      0x1a037124c -[UIViewController dismissViewControllerWithTransition:completion:] + 1236
3  UIKitCore                      0x1a0389128 -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:] + 264
4  UIKitCore                      0x1a0385874 -[_UIViewControllerTransitionContext _runAlongsideCompletions] + 132
5  UIKitCore                      0x1a03855b8 -[_UIViewControllerTransitionContext completeTransition:] + 116
6  UIKitCore                      0x1a0dcbfe0 -[UITransitionView notifyDidCompleteTransition:] + 240
7  UIKitCore                      0x1a0dcbc8c -[UITransitionView _didCompleteTransition:] + 1132
8  UIKitCore                      0x1a0e01d90 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 588
9  UIKitCore                      0x1a0dd5c70 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 244
10 UIKitCore                      0x1a0dd6178 -[UIViewAnimationState animationDidStop:finished:] + 240
11 UIKitCore                      0x1a0dd62c8 -[UIViewAnimationState animationDidStop:finished:] + 576
12 QuartzCore                     0x1a3387dac CA::Layer::run_animation_callbacks(void*) + 276
13 libdispatch.dylib              0x19c5bf184 _dispatch_client_callout + 16
14 libdispatch.dylib              0x19c571190 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1044
15 CoreFoundation                 0x19c8705e4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
16 CoreFoundation                 0x19c86b5d8 __CFRunLoopRun + 2004
17 CoreFoundation                 0x19c86aadc CFRunLoopRunSpecific + 464
18 GraphicsServices               0x1a680b328 GSEventRunModal + 104
19 UIKitCore                      0x1a097863c UIApplicationMain + 1936
20 Stuneo                         0x104a48864 main + 14 (main.m:14)
21 libdyld.dylib                  0x19c6f4360 start + 4

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 24 (12 by maintainers)

Commits related to this issue

Most upvoted comments

@r0b0t3d yes, exactly!

@PointCodeZero Fixed from @phatmann is on his repo. As @vonovak said above, he will fix this issue. While waiting the fix, you could easily apply above workaround by using patch-package and edit the code in RNDocumentPicker.m and add this check

        if (resolve == nil) {
            return;
        }

hi, thanks for the comments, I suspected this would be the case but found it weird that I could not reproduce it. I’ll try to fix this soon by extracting the promise logic into separate class.

The fix was added in 4.3.0

@vonovak could it be closed this issue?

@hungps-2150 My quick thought is that didPickDocumentsAtURLs will be called multiple time. In the first time, resolve was removed by calling [composeResolvers removeLastObject]. So in the second time, resolve will be nil when getting [composeResolvers lastObject].

It is easy for you because you can reproduce the issue. Could you please help to confirm that how many time didPickDocumentsAtURLs was called by adding simple log? And check null for resolve after getting it.

It is something like

- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls
{
    NSLog(@"didPickDocumentsAtURLs");
    if (controller.documentPickerMode == UIDocumentPickerModeImport) {
        RCTPromiseResolveBlock resolve = [composeResolvers lastObject];
        RCTPromiseRejectBlock reject = [composeRejecters lastObject];
        [composeResolvers removeLastObject];
        [composeRejecters removeLastObject];
        
        if (resolve == nil) {
            return;
        }
        NSMutableArray *results = [NSMutableArray array];
        for (id url in urls) {
            NSError *error;
            NSMutableDictionary* result = [self getMetadataForUrl:url error:&error];
            if (result) {
                [results addObject:result];
            } else {
                reject(E_INVALID_DATA_RETURNED, error.localizedDescription, error);
                return;
            }
        }
        
        resolve(results);
    }
}

@phatmann could you reproduce the issue? I tried multiple times on iOS 12.4 (simulator) and 13.5 (simulator + real device) but can not reproduce.