Rare crash during dealloc AVCaptureVideoPreviewLayer
Asked Answered
T

1

6

On client phones rarely can be replicated crash during camera dealloc

Fatal Exception: NSRangeException
Cannot remove an observer <AVCaptureSession 0x174212170> for the key path "changeSeed" from <AVCaptureConnection 0x17420fa60> because it is not registered as an observer.

Thread : Fatal Exception: NSRangeException
0  CoreFoundation                 0x000000018449259c __exceptionPreprocess + 132
1  libobjc.A.dylib                0x0000000194be40e4 objc_exception_throw + 60
2  CoreFoundation                 0x00000001844924dc -[NSException initWithCoder:]
3  Foundation                     0x00000001852a7e9c -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 528
4  Foundation                     0x00000001852a7954 -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 104
5  AVFoundation                   0x0000000182d21054 -[AVCaptureSession _removeConnection:] + 192
6  AVFoundation                   0x0000000182d206dc -[AVCaptureSession _removeVideoPreviewLayer:] + 120
7  AVFoundation                   0x0000000182d300f8 -[AVCaptureVideoPreviewLayer dealloc] + 92

For stop capture session following code is used: All operation with session are precessed in background queue, as stopRunning can take some time

deinit {
  if let session = self.captureSession {
     dispatch_async(self.cameraQueue, { () -> Void in
        session.beginConfiguration()
        let allInputs = session.inputs as! [AVCaptureInput]
        for input in allInputs {
           session.removeInput(input)
        }
        let allOutputs = session.outputs as! [AVCaptureOutput]
        for output in allOutputs {
           session.removeOutput(output)
        }
        session.commitConfiguration()
        session.stopRunning()
     })
  }
}

Has anybody seen this crash before?

Telophase answered 10/4, 2015 at 19:21 Comment(2)
Not an answer, but why bother removing the inputs and outputs? Why not just stopRunning()?Frere
It is recommended here https://mcmap.net/q/762849/-avcapturesession-get-memory-warning-and-crash-with-no-reason, to prevent memory overheadTelophase
V
7

I was also having this exception, and what fixed it for me was unsetting the capture session from the AVCaptureVideoPreviewLayer when I am done with the preview layer (i.e. before discarding the reference to the preview layer). In other words, in some controller I had something like:

previewLayer = AVCaptureVideoPreviewLayer(session: someSession)

where the previewLayer is a property of this controller, and then when I am done with previewLayer, in the deinit of the controller I do:

previewLayer.session = nil

It shouldn't have been necessary to do this, because when the preview layer deinitializes, it nils out the session too. But what I saw happening in the stack traces from the cases that crashed was that the preview layer's dealloc was not being called from the owning controller's dealloc as it normally should, but it was being deallocated from NSKVODeallocate. This means something (KVO related?) must have been holding onto the preview layer after the owning controller deallocates, and only releasing it later. (I don't know what it is or what causes it.) And maybe there is a bug that unsetting the capture session from the preview layer must be done before the capture session is done or it crashes (it shouldn't, but it does). That's why I explicitly unset the session myself when I am done with it.

Vision answered 14/3, 2016 at 23:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.