capawesome-team / capacitor-mlkit

⚑️ ML Kit plugins for Capacitor. Supports Android and iOS.
https://capawesome.io/plugins/mlkit/
Apache License 2.0
147 stars 46 forks source link

bug: Fatal Exception: NSGenericException #176

Closed entspannt closed 1 month ago

entspannt commented 3 months ago

Plugin(s)

Version

6.1.0

Platform(s)

Current behavior

Some users experience iOS crashes caused in BarcodeScannerView.swift: *** -[AVCaptureSession startRunning] startRunning may not be called between calls to beginConfiguration and commitConfiguration

Expected behavior

No crashes

Reproduction

Unfortunately not possible so far

Steps to reproduce

I have not managed to reproduce the crash with my own devices. They occur on iOS 17.6.1 / iPhone 15 Pro Max, iOS 17.5.1 / iPhone 13 Pro, iOS 17.6.1 / iPhone 14 Pro.

Other information

stack trace:

Crashlytics - Stack trace

Fatal Exception: NSGenericException 0 CoreFoundation 0x83f20 __exceptionPreprocess 1 libobjc.A.dylib 0x172b8 objc_exception_throw 2 AVFCapture 0x5bbd8 -[AVCaptureSession startRunning] 3 App 0x16754 thunk for @escaping @callee_guaranteed @Sendable () -> () () 4 libdispatch.dylib 0x213c _dispatch_call_block_and_release 5 libdispatch.dylib 0x3dd4 _dispatch_client_callout 6 libdispatch.dylib 0x15a6c _dispatch_root_queue_drain 7 libdispatch.dylib 0x1609c _dispatch_worker_thread2 8 libsystem_pthread.dylib 0x48f8 _pthread_wqthread 9 libsystem_pthread.dylib 0x10cc start_wqthread

com.apple.main-thread 0 libsystem_kernel.dylib 0x16c8 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x4ec8 mach_msg2_internal + 80 2 libsystem_kernel.dylib 0x4de0 mach_msg_overwrite + 436 3 libsystem_kernel.dylib 0x4c20 mach_msg + 24 4 CoreFoundation 0x53f5c CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x53600 CFRunLoopRun + 1208 6 CoreFoundation 0x52cd8 CFRunLoopRunSpecific + 608 7 GraphicsServices 0x11a8 GSEventRunModal + 164 8 UIKitCore 0x40aae8 -[UIApplication _run] + 888 9 UIKitCore 0x4bed98 UIApplicationMain + 340 10 App 0x4784 main + 5 (AppDelegate.swift:5) 11 ??? 0x1b910b154 (Missing)

com.apple.uikit.eventfetch-thread 0 libsystem_kernel.dylib 0x16c8 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x4ec8 mach_msg2_internal + 80 2 libsystem_kernel.dylib 0x4de0 mach_msg_overwrite + 436 3 libsystem_kernel.dylib 0x4c20 mach_msg + 24 4 CoreFoundation 0x53f5c CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x53600 CFRunLoopRun + 1208 6 CoreFoundation 0x52cd8 CFRunLoopRunSpecific + 608 7 Foundation 0xc7b5c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212 8 Foundation 0xc79ac -[NSRunLoop(NSRunLoop) runUntilDate:] + 64 9 UIKitCore 0x41e81c -[UIEventFetcher threadMain] + 420 10 Foundation 0xde428 NSThreadstart__ + 732 11 libsystem_pthread.dylib 0x606c _pthread_start + 136 12 libsystem_pthread.dylib 0x10d8 thread_start + 8

com.google.firebase.crashlytics.MachExceptionServer 0 libsystem_kernel.dylib 0x16c8 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x4ec8 mach_msg2_internal + 80 2 libsystem_kernel.dylib 0x4de0 mach_msg_overwrite + 436 3 libsystem_kernel.dylib 0x4c20 mach_msg + 24 4 FirebaseCrashlytics 0x1b5bc FIRCLSMachExceptionServer + 104 5 libsystem_pthread.dylib 0x606c _pthread_start + 136 6 libsystem_pthread.dylib 0x10d8 thread_start + 8

com.apple.NSURLConnectionLoader 0 libsystem_kernel.dylib 0x16c8 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x4ec8 mach_msg2_internal + 80 2 libsystem_kernel.dylib 0x4de0 mach_msg_overwrite + 436 3 libsystem_kernel.dylib 0x4c20 mach_msg + 24 4 CoreFoundation 0x53f5c CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x53600 CFRunLoopRun + 1208 6 CoreFoundation 0x52cd8 CFRunLoopRunSpecific + 608 7 CFNetwork 0xfdc7c _CFHostIsDomainTopLevel + 108176 8 Foundation 0xde428 NSThreadstart__ + 732 9 libsystem_pthread.dylib 0x606c _pthread_start + 136 10 libsystem_pthread.dylib 0x10d8 thread_start + 8

JavaScriptCore libpas scavenger 0 libsystem_kernel.dylib 0x708c __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x36e4 _pthread_cond_wait + 1228 2 JavaScriptCore 0x15671e0 scavenger_thread_main + 1316 3 libsystem_pthread.dylib 0x606c _pthread_start + 136 4 libsystem_pthread.dylib 0x10d8 thread_start + 8

Thread 0 libsystem_kernel.dylib 0x1450 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0x4980 _pthread_wqthread + 364 2 libsystem_pthread.dylib 0x10cc start_wqthread + 8

Thread 0 libsystem_kernel.dylib 0x1450 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0x4980 _pthread_wqthread + 364 2 libsystem_pthread.dylib 0x10cc start_wqthread + 8

Thread 0 libsystem_kernel.dylib 0x1450 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0x4980 _pthread_wqthread + 364 2 libsystem_pthread.dylib 0x10cc start_wqthread + 8

Crashed: com.google.firebase.crashlytics.ios.exception 0 FirebaseCrashlytics 0x21c10 FIRCLSProcessRecordAllThreads + 184 1 FirebaseCrashlytics 0x21ff0 FIRCLSProcessRecordAllThreads + 1176 2 FirebaseCrashlytics 0x18e74 FIRCLSHandler + 48 3 FirebaseCrashlytics 0x13a84 FIRCLSExceptionRecord_block_invoke + 96 4 libdispatch.dylib 0x3dd4 _dispatch_client_callout + 20 5 libdispatch.dylib 0x132c4 _dispatch_lane_barrier_sync_invoke_and_complete + 56 6 FirebaseCrashlytics 0x12a00 FIRCLSExceptionRecord + 220 7 FirebaseCrashlytics 0x13548 FIRCLSExceptionRecordNSException + 456 8 FirebaseCrashlytics 0x12608 FIRCLSTerminateHandler() + 404 9 libc++abi.dylib 0x14068 std::terminate(void ()()) + 16 10 libc++abi.dylib 0x1400c std::terminate() + 108 11 libobjc.A.dylib 0x3f81c objc::DenseMapBase<objc::DenseMap<objc_class, PendingInitialize, objc::DenseMapValueInfo<PendingInitialize>, objc::DenseMapInfo<objc_class>, objc::detail::DenseMapPair<objc_class, PendingInitialize> >, objc_class, PendingInitialize, objc::DenseMapValueInfo<PendingInitialize>, objc::DenseMapInfo<objc_class>, objc::detail::DenseMapPair<objc_class, PendingInitialize> >::FatalCorruptHashTables(objc::detail::DenseMapPair<objc_class, PendingInitialize> const, unsigned int) const + 14 12 libdispatch.dylib 0x3de8 _dispatch_client_callout + 40 13 libdispatch.dylib 0x15a6c _dispatch_root_queue_drain + 864 14 libdispatch.dylib 0x1609c _dispatch_worker_thread2 + 156 15 libsystem_pthread.dylib 0x48f8 _pthread_wqthread + 228 16 libsystem_pthread.dylib 0x10cc start_wqthread + 8

Dependencies:

"dependencies": { "@angular/animations": "12.2.10", "@angular/cdk": "12.2.10", "@angular/common": "12.2.10", "@angular/compiler": "12.2.10", "@angular/core": "12.2.10", "@angular/forms": "12.2.10", "@angular/platform-browser": "12.2.10", "@angular/platform-browser-dynamic": "12.2.10", "@angular/router": "12.2.10", "@capacitor-firebase/crashlytics": "^6.1.0", "@capacitor-mlkit/barcode-scanning": "^6.1.0", "@capacitor/android": "^5.0.0", "@capacitor/app": "^6.0.0", "@capacitor/core": "^5.0.0", "@capacitor/ios": "^5.0.0", "@fortawesome/angular-fontawesome": "^0.10.1", "@fortawesome/fontawesome-common-types": "^6.1.0", "@fortawesome/fontawesome-pro": "^6.1.0", "@fortawesome/fontawesome-svg-core": "^6.1.0", "@fortawesome/pro-regular-svg-icons": "^6.1.0", "@fortawesome/pro-solid-svg-icons": "^6.1.0", "@ionic-native/app-version": "^5.36.0", "@ionic-native/camera": "^5.36.0", "@ionic-native/chooser": "^5.36.0", "@ionic-native/core": "^5.36.0", "@ionic-native/device": "^5.36.0", "@ionic-native/file": "^5.36.0", "@ionic-native/http": "^5.36.0", "@ionic-native/in-app-browser": "^5.36.0", "@ionic-native/nfc": "^5.36.0", "@ionic-native/splash-screen": "^5.36.0", "@ionic-native/status-bar": "^5.36.0", "@ionic/angular": "^5.8.4", "@nebular/auth": "^8.0.0", "@nebular/eva-icons": "^8.0.0", "@nebular/moment": "^8.0.0", "@nebular/theme": "^8.0.0", "@ngneat/transloco": "^2.20.1", "@ngrx/data": "^12.5.0", "@ngrx/effects": "12.5.0", "@ngrx/entity": "12.5.0", "@ngrx/router-store": "12.5.0", "@ngrx/schematics": "12.5.0", "@ngrx/store": "12.5.0", "@ngrx/store-devtools": "12.5.0", "@ngx-formly/core": "^5.10.23", "@ngx-formly/ionic": "^5.10.23", "@ngx-formly/schematics": "^5.10.23", "@nrwl/angular": "12.10.0", "@syncfusion/ej2-angular-schedule": "^19.4.55", "@zxing/browser": "^0.1.1", "@zxing/library": "^0.19.1", "@zxing/ngx-scanner": "^3.5.0", "ag-charts-angular": "^5.3.0", "ag-charts-community": "^5.3.0", "ag-grid-angular": "^28.2.1", "ag-grid-community": "^28.2.1", "ag-grid-enterprise": "^28.2.1", "angular-ng-autocomplete": "^2.0.5", "angular2-qrcode": "^2.0.3", "bootstrap": "^5.1.3", "cldr-data": "^36.0.0", "community-cordova-plugin-nfc": "^1.3.0", "cordova-plugin-androidx": "^3.0.0", "cordova-plugin-androidx-adapter": "^1.1.3", "cordova-plugin-app-version": "^0.1.12", "cordova-plugin-camera": "git+https://github.com/DaedalusDev/cordova-plugin-camera.git", "cordova-plugin-chooser": "^1.3.2", "cordova-plugin-device": "^2.0.3", "cordova-plugin-file": "^6.0.2", "cordova-plugin-inappbrowser": "^5.0.0", "cordova-plugin-splashscreen": "^6.0.0", "cypress-wait-until": "^1.7.1", "eva-icons": "^1.1.3", "firebase": "^10.12.5", "ionic-selectable": "^4.9.0", "jetifier": "^1.6.6", "js2xmlparser": "^5.0.0", "moment": "^2.29.1", "ngx-chips": "^2.2.2", "ngx-color": "^7.2.0", "ngx-cookie-service": "^12.0.3", "ngx-dropzone": "^3.0.0", "ngx-image-compress": "^11.0.3", "ngx-permissions": "^8.1.1", "ngx-toastr": "^14.1.3", "rxjs": "6.6.7", "serialize-error": "^8.0.1", "uuid": "^8.3.2", "zone.js": "~0.11.4" },

Capacitor doctor

[warn] The bundledWebRuntime configuration option has been deprecated. Can be safely deleted. πŸ’Š Capacitor Doctor πŸ’Š

Latest Dependencies:

@capacitor/cli: 6.1.2 @capacitor/core: 6.1.2 @capacitor/android: 6.1.2 @capacitor/ios: 6.1.2

Installed Dependencies:

@capacitor/cli: 5.5.1 @capacitor/core: 5.5.1 @capacitor/android: 5.5.1 @capacitor/ios: 5.5.1

[success] iOS looking great! πŸ‘Œ [success] Android looking great! πŸ‘Œ

Before submitting

robingenz commented 3 months ago

*** -[AVCaptureSession startRunning] startRunning may not be called between calls to beginConfiguration and commitConfiguration

That is strange. startRunning is already called after beginConfiguration/commitConfiguration, see https://github.com/capawesome-team/capacitor-mlkit/blob/d3621a3b6e03b99ecb744d23a04154eeb7fada55/packages/barcode-scanning/ios/Plugin/BarcodeScannerView.swift#L66

Unfortunately, I can't debug it if it can't be reproduced.

entspannt commented 2 months ago

I tested a bit and changed the lines to this:

        captureSession.commitConfiguration()
        captureSession.startRunning()

        //DispatchQueue.global(qos: .background).async {
        //    captureSession.startRunning()
        //}

Now the crashes are gone. Can there be a race condition because of the async call?

robingenz commented 2 months ago

@entspannt This change should lead to the following error:

-[AVCaptureSession startRunning] should be called from background thread.

Now the crashes are gone. Can there be a race condition because of the async call?

Not really, as it is called after commitConfiguration.

entspannt commented 2 months ago

@robingenz

This change should lead to the following error: -[AVCaptureSession startRunning] should be called from background thread.

Yes, it shows the purple performance issue in Xcode. I can still build and deploy and it works fine without crashes so that's my preferred option.

I'll keep observing the issue but so far didn't experience any noticeable downside.

Do you have any other suggestions what I can test? Otherwise feel free to close the issue.

robingenz commented 2 months ago

No, unfortunately I can't think of anything. I would like to reproduce and test it myself, but I don't own any of the devices listed above. In this case, I would close the issue for the time being and open it again when similar issues are reported.

ohmnoms commented 2 months ago

@robingenz I'm also seeing this issue on iPhone 12 and iPhone 12 Pro, iOS 17.6.1. Issue occurs during non-continuous scanning when opening, scanning, and reopening the MLKit scanner in rapid succession.

The crashing is inconsistent, but the reported error is the one I get when the app crashes. Similar issues lead me to believe it's related to rapidly opening and closing the camera, but it is inconsistent.

Code for reference:

    async useNativeBarcodeScanner() {
        try {
            const result = await MLKitScanner.scan({
                formats: this.formats as BarcodeFormat[],
            });
            if (result.barcodes.length > 0) {
                this.closeWithValue(result.barcodes[0].displayValue);
            }
        } catch (error) {
            // Error also triggered when MLKitScanner overlay is closed
            console.error('Error using native barcode scanner', error);
            this.dialogRef.close();
        }
    }
robingenz commented 2 months ago

The crashing is inconsistent, but the reported error is the one I get when the app crashes. Similar issues lead me to believe it's related to rapidly opening and closing the camera, but it is inconsistent.

Seems like this is their solution: https://github.com/aws/amazon-chime-sdk-ios/commit/3f1e6c81e22b36af7a16e492248fac1bad7397da#diff-12e8c49a92f69a9db2508a80314e24d74e4ed1f1cef5f5a781b5cb2fe399784aR155

I will create a dev release for testing.

robingenz commented 1 month ago

@ohmnoms Sorry for my late reply. This is the dev version:

npm i https://pkg.pr.new/capawesome-team/capacitor-mlkit/@capacitor-mlkit/barcode-scanning@188

Let me know if this helps you.

ohmnoms commented 1 month ago

@robingenz I appreciate it! I've applied the dev version and am not seeing any errors in the initial test. Will do more testing on other devices shortly and I'll update if I see the error persist.