4

由 xpc_connection_send_message_with_reply_sync 超时引发的崩溃

 1 year ago
source link: https://kanchuan.com/blog/195-xpc-reply-sync
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

由 xpc_connection_send_message_with_reply_sync 超时引发的崩溃

 原创    2023-09-01

iOS 的一些系统接口需要调用 xpc_connection_send_message_with_reply_sync 方法与其它进程通信并返回结果,在低性能设备上打开 APP 后如果有频繁的 xpc_reply_sync 调用可能会诱发超时卡死。

跟踪线上问题时发现一个少量的 Crash Case,错误描述为:

Termination Reason:<RBSTerminateContext| domain:10 code:0x8BADF00D explanation:scene-create watchdog transgression: application<com.kanchuan.app>:226 exhausted real (wall clock) time allowance of 13.54 seconds

Crash 线程堆栈部分如下:

Thread 0 Crashed:
0      libsystem_kernel.dylib        	_mach_msg_trap
1      libsystem_kernel.dylib        	_mach_msg
2      libdispatch.dylib             	__dispatch_mach_send_and_wait_for_reply
3      libdispatch.dylib             	_dispatch_mach_send_with_result_and_wait_for_reply$VARIANT$mp
4      libxpc.dylib                  	_xpc_connection_send_message_with_reply_sync
5      Foundation                    	___NSXPCCONNECTION_IS_WAITING_FOR_A_SYNCHRONOUS_REPLY__
6      Foundation                    	-[NSXPCConnection _sendInvocation:orArguments:count:methodSignature:selector:withProxy:]
7      Foundation                    	-[NSXPCConnection _sendSelector:withProxy:arg1:]
8      Foundation                    	__NSXPCDistantObjectSimpleMessageSend1
9      CoreLocation                  	_CLGetStatusBarIconState
10     CoreLocation                  	_CLClientIsLocationServicesEnabled
11     CoreLocation                  	_CLClientRetrieveAuthorizationStatus

对应的源码调用入口为:

[CLLocationManager locationServicesEnabled];

由于业务的特殊要求,之前曾对 CLLocationManager的弹窗问题 做过处理,在打开 APP 后会判断系统定位服务是否开启。就这么简单的一个调用竟然能引起线上一天十几个设备的 Crash。

从已知的信息上来,这又是一起典型的因 APP 卡死超时导致被 watchdog 关闭的 Crash。Crash 集中发生在 iPhone 6s、iPhone 7 等低端设备上,且大部分都是 iOS 15.7 系统,也有一些 iOS 16 系统,表现为在打开 APP 后即 Crash。问题似乎已经很明显了,当我准备复现问题时,发现就算找到了对应的设备和系统,再加上人为营造苛刻的测试环境,都始终无法复现问题。哎,这类问题看来只能到线上放量时才能暴露出来。

xpc_connection_send_message_with_reply_sync

XPC(XPC Services)是在 iOS 和 macOS 系统中用于进程间通信(IPC)的框架,用于在不同的应用程序或进程之间进行安全且高效的数据交换。开发者在上层应用调用的一些系统 API 都需要通过 libxpc.dylib 中的 xpc_connection_send_message_with_reply_sync 方法同步从系统对应的服务中获取结果并返回,比如 UIDevice.identifierForVendor、NSUserDefaults、UIApplication.openURL等,CLLocationManager.locationServicesEnabled 内部也通过该方法向系统定位服务查询结果。

对应的还有一个 xpc_connection_send_message_with_reply,这是一个异步方法,不会存在超时的问题。典型的,Runloop的 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__事件回调就是通过 xpc_connection_send_message_with_reply 发送 XPC 消息,用于处理 UI 事件。

问题出现的可能原因

由于始终无法复现问题,这里只能猜测原因:很可能是在 APP 启动时,在多线程环境中执行了太多需要触发 xpn reply sync 调用的方法(一个很不起眼的系统方法内部都可能调用了xpn reply sync),导致内部消息处理出现了问题,一直无法返回,直到被 watchdog 杀死。考虑到错误集中在 iOS 15.7 系统上,有理由怀疑是 iOS 15.7 引入的 bug。

如何修复?

  1. 检查系统启动时调用 xpc_connection_send_message_with_reply_sync 的频次,能后移的尽量后移;
  2. 尽量避免调用能触发 xpc_connection_send_message_with_reply_sync 的接口。

比如 kanchuan 遇到的这个 locationServicesEnabled 问题,在主线程调用时,可能会收到提醒:

This method can cause UI unresponsiveness if invoked on the main thread

推荐在 CLLocationManager 的 delegate 中监听定位权限的变化(代理是由系统回调的,不会存在 xpn reply sync 问题 ),当定位状态开启后再执行业务逻辑:

- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
    if (@available(iOS 14.0, *)) {
        CLAuthorizationStatus status = manager.authorizationStatus;
        if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        }
    } else {
        // Fallback on earlier versions
    }
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
    }
}

以上修改发布到新版本后,Crash 得到解决。

 iOS  

相关文章:

iOS 真机和模拟器HTTPS Charles抓包指南
iOS安全:Tweak clang: warning: libstdc++ is deprecated
iOS crash log分析实践
iOS WKWebView详解及JS Bridge同步调用问题
iOS安全:使用frida-ios-dump砸壳

wechat.png

您的电子邮箱地址不会被公开,必填项已用*标注。

留言内容 *

显示名称 *

电子邮箱地址 *

个人网站地址

在此浏览器中保存我的显示名称、邮箱地址和网站地址,以便下次留言时使用。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK