Contents
  1. 1. 结论
Thread 0:
0   libsystem_kernel.dylib          kevent_id + 8
1   libdispatch.dylib               _dispatch_kq_poll + 332
2   libdispatch.dylib               _dispatch_event_loop_wait_for_ownership$VARIANT$mp + 412
3   libdispatch.dylib               __DISPATCH_WAIT_FOR_QUEUE__ + 292
4   libdispatch.dylib               _dispatch_sync_f_slow + 140
5   my_process                      [class doSomething]

主线程出现这样的卡死状态,第四个函数调用就是 dispatch_sync。这里就不去看 dispatch_sync_f_slow 的源码了,看了也没啥卵用,除了让本文看起来高级难懂些没啥卵用。

一开始想不明白为什么会卡死,看到其他线程的栈帧突然明白了。

Thread 12:
0   libsystem_kernel.dylib          mach_msg_trap + 8
1   libsystem_kernel.dylib          mach_msg + 72
2   libdispatch.dylib               _dispatch_mach_send_and_wait_for_reply + 564
3   libdispatch.dylib               dispatch_mach_send_with_result_and_wait_for_reply$VARIANT$mp + 52
4   libxpc.dylib                    xpc_connection_send_message_with_reply_sync + 236
5   Foundation                      __NSXPCCONNECTION_IS_WAITING_FOR_A_SYNCHRONOUS_REPLY__ + 12
6   Foundation                      -[NSXPCConnection _sendInvocation:orArguments:count:methodSignature:selector:withProxy:] + 2608
7   Foundation                      -[NSXPCConnection _sendSelector:withProxy:arg1:arg2:] + 136
8   Foundation                      _NSXPCDistantObjectSimpleMessageSend2 + 40
9   MediaPlaybackCore               -[MPCRemotePlaybackEngine _updatePlayerPath] + 200
10  MediaPlaybackCore               -[MPCRemotePlaybackEngine _initializePlaybackStack] + 360
11  MediaPlaybackCore               -[MPCPlaybackEngine initWithPlayerID:options:] + 208
12  MediaPlayer                     -[MPMusicPlayerApplicationController _initWithClientIdentifier:] + 180
13  MediaPlayer                     __49+[MPMusicPlayerController applicationQueuePlayer]_block_invoke + 40
14  libdispatch.dylib               _dispatch_client_callout + 16
15  libdispatch.dylib               _dispatch_once_callout + 28
16  MediaPlayer                     +[MPMusicPlayerController applicationQueuePlayer] + 56
17  my_process                      [class doSomething]

原来是因为有的地方提前使用 dispatch_async 调用了这个 doSomething 同步方法,这个同步方法使用了一个串行队列进行消费。但是走到 MPMusicPlayerController 这里的时候 xpc 服务卡了。这个时候串行队列的任务没执行完,主线程又往这个队列里丢了一个同步任务,于是主线程就在一直等待了。

结论

所以呢,内部使用的同步队列要有足够的局部性。如果因为这样那样的原因暴露给了外部,就容易出问题了。

Contents
  1. 1. 结论