twostraws / CodeScanner

A SwiftUI view that is able to scan barcodes, QR codes, and more, and send back what was found.
MIT License
1.01k stars 286 forks source link

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

Closed priconceptions closed 2 years ago

priconceptions commented 2 years ago

Hi,

I am seeing crashes in production when I updated to the latest version of Code Scanner. I can't seem to reproduce this issue but it's happening to many of our users. Here are some of the breadcrumbs before this issue occurs:

Does anyone have any insights on how to fix this issue?

Jesus commented 2 years ago

I believe this is a consequence of moving the call to startRunning() to a background thread, by doing that the execution order isn't guaranteed anymore so if it gets called while configuration changes are happening the crash will happen.

I'm not sure yet what a good fix would be. If we move the call to startRunning() back to the main thread we'd be blocking it which is also bad.

Jesus commented 2 years ago

Here's the full crash report:

OS Version: iOS 15.3.1 (19D52)
Report Version: 104

Exception Type: EXC_CRASH (SIGABRT)
Crashed Thread: 11

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

Thread 11 Crashed:
0   CoreFoundation                  0x30073bd3c         <redacted>
1   libobjc.A.dylib                 0x32eeac6a4         objc_exception_throw
2   AVFCapture                      0x346327690         -[AVCaptureSession startRunning]
3   Wave                            0x202d10aa8         thunk for closure
4   libdispatch.dylib               0x3001011a0         _dispatch_call_block_and_release
5   libdispatch.dylib               0x3001021a4         _dispatch_client_callout
6   libdispatch.dylib               0x3000b1564         _dispatch_root_queue_drain
7   libdispatch.dylib               0x3000b1c34         _dispatch_worker_thread2
8   libsystem_pthread.dylib         0x3b5452e44         _pthread_wqthread
9   libsystem_pthread.dylib         0x3b54529ec         start_wqthread

Thread 0
0   libsystem_kernel.dylib          0x374a18b10         mach_msg_trap
1   libsystem_kernel.dylib          0x374a19130         mach_msg
2   CoreFoundation                  0x3006b0b60         <redacted>
3   CoreFoundation                  0x3006b4c48         <redacted>
4   CoreFoundation                  0x3006c7e1c         CFRunLoopRunSpecific
5   GraphicsServices                0x340e2999c         GSEventRunModal
6   UIKitCore                       0x305261b8c         -[UIApplication _run]
7   UIKitCore                       0x304ff7168         UIApplicationMain
8   Wave                            0x20298882c         main (AcceptLanguageInterceptor.swift:10)
9   <unknown>                       0x103170250         <redacted>

Thread 1 name: com.apple.uikit.eventfetch-thread
0   libsystem_kernel.dylib          0x374a18b10         mach_msg_trap
1   libsystem_kernel.dylib          0x374a19130         mach_msg
2   CoreFoundation                  0x3006b0b60         <redacted>
3   CoreFoundation                  0x3006b4c48         <redacted>
4   CoreFoundation                  0x3006c7e1c         CFRunLoopRunSpecific
5   Foundation                      0x3035433dc         <redacted>
6   Foundation                      0x303581c4c         <redacted>
7   UIKitCore                       0x3051df8a8         -[UIEventFetcher threadMain]
8   Foundation                      0x30358f8bc         <redacted>
9   libsystem_pthread.dylib         0x3b54543a0         _pthread_start

Thread 2
0   libsystem_kernel.dylib          0x374a19088         __semwait_signal
1   libsystem_c.dylib               0x3151948dc         nanosleep
2   libsystem_c.dylib               0x3151a8288         sleep
3   Wave                            0x202e06768         monitorCachedData (SentryCrashCachedData.c:139)
4   libsystem_pthread.dylib         0x3b54543a0         _pthread_start

Thread 3 name: SentryCrash Exception Handler (Secondary)
0   libsystem_kernel.dylib          0x374a18b10         mach_msg_trap
1   libsystem_kernel.dylib          0x374a19130         mach_msg
2   libsystem_kernel.dylib          0x374a23ff8         thread_suspend
3   Wave                            0x202e02178         handleExceptions (SentryCrashMonitor_MachException.c:258)
4   libsystem_pthread.dylib         0x3b54543a0         _pthread_start

Thread 4 name: SentryCrash Exception Handler (Primary)
0   libsystem_kernel.dylib          0x374a18b10         mach_msg_trap
1   libsystem_kernel.dylib          0x374a19130         mach_msg
2   Wave                            0x202e021a4         handleExceptions (SentryCrashMonitor_MachException.c:266)
3   libsystem_pthread.dylib         0x3b54543a0         _pthread_start

Thread 5 name: io.sentry.anr-tracker
0   libsystem_kernel.dylib          0x374a19088         __semwait_signal
1   libsystem_c.dylib               0x3151948dc         nanosleep
2   Foundation                      0x3035a13c0         <redacted>
3   Wave                            0x202dc0380         -[SentryANRTracker detectANRs] (SentryANRTracker.m:67)
4   Foundation                      0x30358f8bc         <redacted>
5   libsystem_pthread.dylib         0x3b54543a0         _pthread_start

Thread 6 name: AVAudioSession Notify Thread
0   libsystem_kernel.dylib          0x374a18b10         mach_msg_trap
1   libsystem_kernel.dylib          0x374a19130         mach_msg
2   CoreFoundation                  0x3006b0b60         <redacted>
3   CoreFoundation                  0x3006b4c48         <redacted>
4   CoreFoundation                  0x3006c7e1c         CFRunLoopRunSpecific
5   AudioSession                    0x311ee3d78         CADeprecated::GenericRunLoopThread::Entry
6   AudioSession                    0x311eed0a8         CADeprecated::CAPThread::Entry
7   libsystem_pthread.dylib         0x3b54543a0         _pthread_start

Thread 7 name: com.apple.NSURLConnectionLoader
0   libsystem_kernel.dylib          0x374a18b10         mach_msg_trap
1   libsystem_kernel.dylib          0x374a19130         mach_msg
2   CoreFoundation                  0x3006b0b60         <redacted>
3   CoreFoundation                  0x3006b4c48         <redacted>
4   CoreFoundation                  0x3006c7e1c         CFRunLoopRunSpecific
5   CFNetwork                       0x3018a4da4         _CFURLStorageSessionCopyIdentifier
6   Foundation                      0x30358f8bc         <redacted>
7   libsystem_pthread.dylib         0x3b54543a0         _pthread_start

Thread 8
0   libsystem_kernel.dylib          0x374a190cc         __workq_kernreturn
1   libsystem_pthread.dylib         0x3b5452ecc         _pthread_wqthread

Thread 9
0   libsystem_kernel.dylib          0x374a190cc         __workq_kernreturn
1   libsystem_pthread.dylib         0x3b5452ecc         _pthread_wqthread

Thread 10
0   libsystem_kernel.dylib          0x374a190cc         __workq_kernreturn
1   libsystem_pthread.dylib         0x3b5452ecc         _pthread_wqthread

Thread 11 Crashed:
0   CoreFoundation                  0x30073bd3c         <redacted>
1   libobjc.A.dylib                 0x32eeac6a4         objc_exception_throw
2   AVFCapture                      0x346327690         -[AVCaptureSession startRunning]
3   Wave                            0x202d10aa8         thunk for closure
4   libdispatch.dylib               0x3001011a0         _dispatch_call_block_and_release
5   libdispatch.dylib               0x3001021a4         _dispatch_client_callout
6   libdispatch.dylib               0x3000b1564         _dispatch_root_queue_drain
7   libdispatch.dylib               0x3000b1c34         _dispatch_worker_thread2
8   libsystem_pthread.dylib         0x3b5452e44         _pthread_wqthread
9   libsystem_pthread.dylib         0x3b54529ec         start_wqthread

Thread 12
0   libsystem_platform.dylib        0x3b543b0d0         os_unfair_recursive_lock_lock_with_options$VARIANT$mp
1   libobjc.A.dylib                 0x32ee9c8c8         objc_sync_enter
2   AVFCapture                      0x3462fc1f4         -[AVCaptureSession _updateCameraCalibrationDataDeliveryEnabledForSourceDevice:]
3   AVFCapture                      0x346399c9c         -[AVCaptureSession _buildAndRunGraph:]
4   AVFCapture                      0x346317f00         -[AVCaptureSession _commitConfiguration]
5   Foundation                      0x30355bb28         <redacted>
6   Foundation                      0x303548194         <redacted>
7   Foundation                      0x30357f4f8         <redacted>
8   AVFCapture                      0x346307b5c         -[AVCaptureMetadataOutput setMetadataObjectTypes:]
9   Wave                            0x202d10a4c         CodeScannerView.ScannerViewController.viewDidLoad (ScannerViewController.swift:195)
10  Wave                            0x202d10ae0         thunk for closure
11  libdispatch.dylib               0x3001011a0         _dispatch_call_block_and_release
12  libdispatch.dylib               0x3001021a4         _dispatch_client_callout
13  libdispatch.dylib               0x3000a41f8         _dispatch_queue_override_invoke
14  libdispatch.dylib               0x3000b1438         _dispatch_root_queue_drain
15  libdispatch.dylib               0x3000b1c34         _dispatch_worker_thread2
16  libsystem_pthread.dylib         0x3b5452e44         _pthread_wqthread

Thread 13
0   AVFCore                         0x311f5818c         __destroy_helper_block_e8_32o40o48o
1   libsystem_blocks.dylib          0x3b5341830         _Block_release
2   libdispatch.dylib               0x3001021a4         _dispatch_client_callout
3   libdispatch.dylib               0x3000b04c8         _dispatch_lane_concurrent_drain
4   libdispatch.dylib               0x3000a8c14         _dispatch_lane_invoke$VARIANT$mp
5   libdispatch.dylib               0x3000a40cc         _dispatch_queue_override_invoke
6   libdispatch.dylib               0x3000b1438         _dispatch_root_queue_drain
7   libdispatch.dylib               0x3000b1c34         _dispatch_worker_thread2
8   libsystem_pthread.dylib         0x3b5452e44         _pthread_wqthread

Something I found interesting is that thread 12 is in viewDidLoad() (and hasn't finished its call to commitConfiguration()) while thread 11 is already calling startRunning() in viewWillAppear(). This doesn't make sense to me because I would assume viewWillAppear() wouldn't start until viewDidLoad() had finished.

Jesus commented 2 years ago

Oh but the related code is wrapped in the requestAccess() callback, which might happen after viewDidLoad is over.

Jesus commented 2 years ago

Ok I'm pretty sure the solution is to do the permission checking somewhere else, the way it was implemented in https://github.com/twostraws/CodeScanner/pull/49 causes the configuration changes to potentially happen during/after we call startRunning.

In our app in particular, we handle the permission logic ourselves and I'd assume that's what every other app that uses this library is doing because there was no logic to handle permissions prior to that PR.

Additionally, that PR doesn't really change behavior based on the permission state. Here, I would expect the block param not to be ignored and the code to look something like this:

AVCaptureDevice.requestAccess(for: .video) { success in
    if success {
        // something
    } else {
        // something else
    }

With all of that, I think it would be a good idea to revert it so I'm about to submit a revert PR for your consideration.

Mrteller commented 2 years ago

I can confirm the issue @Jesus. Permission check does not look like a part of this component functionality. Think that reverting #71 is good idea.

twostraws commented 2 years ago

That change has been reverted, and another put in its place – hopefully this is improved.