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:

使用捕获所有未处理异常的NSProxyNSXPCConnection 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 和异常处理的主要内容,如果未能解决你的问题,请参考以下文章

哪个处理程序在 macos xpc 中处理来自服务器的回复

Java中的异常处理机制的简单原理和应用。

约束和异常处理 20

当 launchd 终止进程时是不是调用 XPC 中断处理程序?

Java中的异常处理机制的简单原理和应用。

在异常处理结构中可以出现多个catch语句和多个finally语句来处理各种异常吗?