XPC 和异常处理
Posted
技术标签:
【中文标题】XPC 和异常处理【英文标题】:XPC and Exception handling 【发布时间】:2019-03-03 09:22:49 【问题描述】:我有一个 LaunchAgent 使用 HockeyApp 进行崩溃报告。现在我注意到 HockeyApp 没有报告未捕获的异常,就像在普通的 macOS 应用程序中一样。
例如:
- (void)upperCaseString:(NSString *)aString withReply:(void (^)(NSString *))reply
NSArray *array = [NSArray array];
reply([array objectAtIndex:23]);
从未到达NSUncaughtExceptionHandler
,但控制台记录:
<NSXPCConnection: 0x7fe97dc0f110> connection from pid 44573: Warning: Exception caught during invocation of received message, dropping incoming message and invalidating the connection.
问题是如何使用 HockeyApp 报告未处理的异常。
【问题讨论】:
【参考方案1】:问题:
XPC 似乎有自己的@try @catch 块,它在方法中捕获未处理的异常,记录异常,然后调用-[NSXPCConnection interruptionHandler]
。
此问题已通过rdar://48543049 报告给 Apple。
注意:这些是不是复制和过去的解决方案,请仔细评估您的崩溃报告框架。我链接到 PLCrashReporter 的实现细节。
解决方案 A:
@try @catch 块:
- (void)upperCaseString:(NSString *)aString withReply:(void (^)(NSString *))reply
@try
NSArray *array = [NSArray array];
reply([array objectAtIndex:23]);
@catch (NSException *exception)
NSUncaughtExceptionHandler *handler = NSGetUncaughtExceptionHandler();
if (handler)
handler(exception);
讨论
HockeyApp 使用 PLCrashReporter 进行崩溃报告。 PLCrashReporter 注册了一个NSUncaughtExceptionHandler
(code)。所以上面的代码会将异常转发给 PLCrashReporter 异常处理程序并终止 (code) XPC。
Mattie 建议再次@throw 异常,以触发内部 XPC @catch 块以及可能的内部清理和日志记录。 这是需要考虑的事情。特别是如果您在连接的 LaunchAgent/Server 端的 NSXPCConnection
上有一个自定义的 interruptionHandler
!
现在我不会再扔它了,因为 我的 XPC 是完全无状态的,崩溃应该没问题。
解决方案 A 的缺点是通过 XPC 公开的每个方法都需要这个 @try @catch 块。
解决方案 B:
使用捕获所有未处理异常的NSProxy
NSXPCConnection exportObject
:
@interface LOUncaughtExceptionHandlerProxy : NSProxy
NSObject *_object;
@end
@implementation LOUncaughtExceptionHandlerProxy
- (instancetype)initWithObject:(NSObject *)object
NSParameterAssert(object);
_object = object;
return self;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
return [_object methodSignatureForSelector:selector];
- (void)forwardInvocation:(NSInvocation *)invocation
@try
[invocation invokeWithTarget:_object];
@catch (NSException *exception)
NSUncaughtExceptionHandler *handler = NSGetUncaughtExceptionHandler();
if (handler)
handler(exception);
@end
在NSXPCListener
监听器中设置:
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
XPC *exportedObject = [XPC new];
LOUncaughtExceptionHandlerProxy *proxy = [[LOUncaughtExceptionHandlerProxy alloc] initWithObject:exportedObject];
newConnection.exportedObject = proxy;
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
[newConnection resume];
return YES;
解决方案 A 的所有详细信息都适用于解决方案 B。
解决方案 Z:
在 macOS 上可以使用 ExceptionHandling.framework,它的问题在BITCrashExceptionApplication.h 中有很好的概述。
讨论
如果框架未移植到 ios,这绝不是一个好兆头。另请注意Matties 评论:
我与 Apple 的互动直接表明 ExceptionHandling.framework 不再受支持。而且,根据我在 Crashlytics 上工作的经验,它存在一些基本的互操作性问题,超出了引用 header 中所指出的问题。
【讨论】:
方案1很棒,方案2很聪明!但是,我会考虑在@catch
块的末尾添加一个 @throw
语句。现在,您正在更改运行时行为——尽管这可能是您的意图。另外:我与 Apple 的交互直接表明 ExceptionHandling.framework 不再受支持。而且,根据我在 Crashlytics 上工作的经验,它存在一些基本的互操作性问题,超出了引用的标题中指出的问题。不过,恐怕我没有记录这些细节。以上是关于XPC 和异常处理的主要内容,如果未能解决你的问题,请参考以下文章