XPC和异常处理

问题描述 投票:1回答:1

我有一个使用HockeyApp的LaunchAgent进行崩溃报告。现在我注意到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报告未处理的异常。

objective-c cocoa cocoa-touch xpc nsxpcconnection
1个回答
1
投票

Problem:

XPC似乎有自己的@try @catch块,它捕获方法中的未处理异常,记录异常,然后调用-[NSXPCConnection interruptionHandler]

这个问题是根据rdar://48543049向Apple报告的。

注意:这些不是复制和过去的解决方案,请仔细评估您的崩溃报告框架。我链接到PLCrashReporter的实现细节。

Solution 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注册了一个NSUncaughtExceptionHandlercode)。因此,上面的代码会将异常转发给PLCrashReporter异常处理程序并终止(code)XPC。

Mattie建议再次@throw异常,触发内部XPC @catch块以及可能的内部清理和日志记录。这是需要考虑的事情。特别是如果你在连接的LaunchAgent / Server端的interruptionHandler上有一个自定义的NSXPCConnection

现在我一边不再扔它,因为我的XPC是完全无状态的,应该很好,只是崩溃。

解决方案A的缺点是通过XPC公开的每个方法都需要@try @catch块。

Solution 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.

Solution Z:

在macOS上可以使用ExceptionHandling.framework,它的问题在BITCrashExceptionApplication.h中有很好的概述。

讨论

当框架未移植到iOS时,这绝不是一个好兆头。另请注意Matties评论:

我与Apple进行了交互,直接表明不再支持ExceptionHandling.framework。而且,根据我在Crashlytics工作期间的经验,它有一些基本的互操作性问题,超出了引用的header所指出的内容。

© www.soinside.com 2019 - 2024. All rights reserved.