dispatch_sync_f_slow 主线程死锁
Contents
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 服务卡了。这个时候串行队列的任务没执行完,主线程又往这个队列里丢了一个同步任务,于是主线程就在一直等待了。
结论
所以呢,内部使用的同步队列要有足够的局部性。如果因为这样那样的原因暴露给了外部,就容易出问题了。