XPC и обработка исключений - PullRequest
0 голосов
/ 03 марта 2019

У меня есть LaunchAgent , использующий HockeyApp для отчетов о сбоях.Теперь я заметил, что uncauched исключение не сообщается 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 Ответ

0 голосов
/ 03 марта 2019

Проблема:

Кажется, что XPC имеет свой собственный @ try @catch block , который перехватывает необработанные исключения внутри метода, регистрирует исключение и затем вызывает -[NSXPCConnection interruptionHandler].

Об этой проблеме сообщается в Apple по адресу rdar: //48543049.

ПРИМЕЧАНИЕ: Это , а не copy &прошлые решения, тщательно оцените свою структуру отчетности о сбоях.Я ссылаюсь на детали реализации PLCrashReporter .

Решение A:

@ try @catch block :

- (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 ( код ).Таким образом, приведенный выше код перенаправит исключение в обработчик исключений PLCrashReporter и завершит ( code ) XPC.

Мэтти предлагает снова @ throw исключение, чтобы вызвать внутренний блок XPC @ catch и возможную внутреннюю очистку и ведение журнала. Это то, что нужно учитывать .Особенно, если у вас есть пользовательский interruptionHandler на NSXPCConnection на стороне LaunchAgent / Server соединения!

Пока я не собираюсь снова его бросать, потому что мой XPC полностью лишен состояния и должен работать только после сбоя.

Недостаток Решение A заключается в том, что каждый метод, предоставляемый через XPC, требует @ try @catch block .

Решение 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;
}

Все детали Solution A относятся к Solution B .

Solution Z:

В macOS можно использовать ExceptionHandling.framework, проблемы с ним очень хорошо изложены в BITCrashExceptionApplication.h .

Обсуждение

Это никогда не является хорошим признаком, когдафреймворк не портирован на iOS.Также обратите внимание Matties комментарий:

У меня были взаимодействия с Apple, которые прямо указывают на то, что ExceptionHandling.framework больше не поддерживается.И, по моему опыту, работая над Crashlytics, у него были некоторые фундаментальные проблемы взаимодействия, помимо того, что указано в указанном заголовке .

...