12

I got a weird crash when using AVPlayer to play a remote video. From the crash log on Fabric, the App crash on system thread (com.apple.avfoundation.playerlayer.configuration). The crash log is below:

Crashed: com.apple.avfoundation.playerlayer.configuration
0  libsystem_kernel.dylib         0x1839ac2e8 __pthread_kill + 8
1  libsystem_pthread.dylib        0x183ac12f8 pthread_kill$VARIANT$mp + 396
2  libsystem_c.dylib              0x18391afbc abort + 140
3  libsystem_malloc.dylib         0x1839e3ce4 szone_size + 634
4  QuartzCore                     0x187ed75e8 -[CALayer dealloc] + 72
5  QuartzCore                     0x187e75d90 CA::Transaction::commit() + 1052
6  AVFoundation                   0x18973b4a8 -[AVPlayerLayer observeValueForKeyPath:ofObject:change:context:] + 684
7  Foundation                     0x1847a2894 NSKeyValueNotifyObserver + 304
8  Foundation                     0x1847bc364 -[NSObject(NSKeyValueObserverRegistration) _addObserver:forProperty:options:context:] + 204
9  Foundation                     0x1847bc13c -[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] + 124
10 AVFoundation                   0x189760714 -[AVPlayer addObserver:forKeyPath:options:context:] + 204
11 AVFoundation                   0x189890414 -[AVKVODispatcher startObservingValueAtKeyPath:ofObject:options:usingBlock:] + 136
12 AVFoundation                   0x18989189c -[AVKVODispatcher(LegacyCallbackMethod) startObservingObject:weakObserver:forKeyPath:options:context:] + 152
13 AVFoundation                   0x18973aef4 -[AVPlayerLayer _startObservingPlayer:] + 328
14 libdispatch.dylib              0x183816a54 _dispatch_call_block_and_release + 24
15 libdispatch.dylib              0x183816a14 _dispatch_client_callout + 16
16 libdispatch.dylib              0x18382096c _dispatch_queue_serial_drain$VARIANT$mp + 528
17 libdispatch.dylib              0x1838212fc _dispatch_queue_invoke$VARIANT$mp + 340
18 libdispatch.dylib              0x183821d20 _dispatch_root_queue_drain_deferred_wlh$VARIANT$mp + 404
19 libdispatch.dylib              0x18382a03c _dispatch_workloop_worker_thread$VARIANT$mp + 644
20 libsystem_pthread.dylib        0x183abef1c _pthread_wqthread + 932
21 libsystem_pthread.dylib        0x183abeb6c start_wqthread + 4

Notice: all of the crash happened on iOS11

Does anybody have an idea why this crash occurred?

Masoud Zarjani
  • 410
  • 1
  • 8
  • 19
VanTrickster
  • 161
  • 1
  • 4
  • Share the code where crash is indicated. – Nitish Feb 04 '18 at 12:20
  • 3
    Please read how to create a [mcve] and add the missing information to your Post by editing it :) If you haven't read [ask] yet i recommend to do so :) I highly recommend to follow the 2 guides i linked as the people on SO are more likely to answer questions when the posts follow these guides. What i'm missing in particular is - What have u tried so far? What errors/problems do you face? Do you may have codesnippets that show what you tried so far? Welcome to StackOverflow – Tobias Theel Feb 04 '18 at 12:30
  • same problem here do u solve it ? – Kodr.F May 15 '18 at 08:23
  • why is the CALayer dealloc before :Transaction::commit() , is this for some other layer ? – Majid Bashir May 17 '18 at 05:05
  • @MajidBashir You're reading the stack trace incorrectly; read from bottom-to-top. This is saying that `[CALayer dealloc]` was called by `CA::Transaction::commit()` – christopherdrum May 18 '18 at 01:21
  • `AVPlayerLayer observeValueForKeyPath:ofObject:change:context:` looks to me to be the place to start. What object is AVPlayer being asked to watch? What might cause that object to be dealloc'd earlier than expected? Does that object actually conform to the keyPath you're trying to observe? Without specific app code to compare against, a stack trace like this can be close to indecipherable. – christopherdrum May 18 '18 at 01:24

1 Answers1

10

From your stack trace, I noticed that AVPlayerLayer observeValueForKeyPath:ofObject:change:context: seems to be the cause of your issue. Hence I believe you must be implementing KVO for AVPlayer.

In which case, note two points:

  1. With the new Key-Value-Observing iOS 11 API you have relaxed requirements, however these requirements for not having to deregister from observations only apply under the following conditions:

Relaxed Key-Value Observing Unregistration Requirements

• The object must be using KVO autonotifying, rather than manually calling -will and -didChangeValueForKey: (i.e. it should not return NO from +automaticallyNotifiesObserversForKey:).

• The object must not override the (private) accessors for internal KVO state.

See here to see this being implemented in the new API with the old API addObserver and removeObserver methods. Note that the documentation is not very helpful for the new API as yet because it still is based on the old KVO implementation. But, as you can see deregistering happens automatically on deinit.

AVFoundation hides the implementation of AVPlayer for KVO support (it's a private framework), but it is likely that these relaxed requirements do not apply for AVPlayer. This code snippet from Apple in 2018, uses AVPlayer with the new KVO API, but still deregisters in a deinit method (confirming suspicions that AVPlayer does not meet the relaxed unregistration requirements for the new API).

Another explanation is that deregistering happens in deinit, but not necessarily done in the main thread. This is important for AVPlayer KVO.

  1. The reason this is important can be found from the docs:

General State Observations: You should register and unregister for KVO change notifications on the main thread. This avoids the possibility of receiving a partial notification if a change is being made on another thread.

In summary, if implementing KVO for AVPlayer with the new API, you need to explicitly unregister when you're done. Also, wrap your registering and unregistering code inside a DispatchQueue.main.async { } or similar variant.

I have assumed here that your key path is valid (just make sure they are dynamic properties).

Pranav Kasetti
  • 8,770
  • 2
  • 50
  • 71
  • Hey Pranav, I have a similar crash and I think I do the correct unregistration. Would you be so kind to take a look at my question here https://stackoverflow.com/questions/52479027/nskeyvalueobservation-cannot-remove-an-observer-for-the-key-path-from-object-be – iur Sep 27 '18 at 15:11
  • 1
    This is awesome, not removing the observers on deinit was causing me a lot of crashes. Thanks! – TNguyen Jul 23 '19 at 18:44
  • I came across the question with a similar issue affecting only iOS 12 but not iOS 13 and iOS 14. Just leaving this info ... – Reimond Hill Jan 08 '21 at 11:51