在dispatch_once块内捕获异常

7

在处理苹果的按需资源框架时,我的应用程序发现有一部分用户会产生许多异常。我第一次尝试解决这个问题是将我的代码放入@try/@catch块中,但不幸的是,崩溃仍然传播。我已经缩小了问题的范围,但不确定如何解决它。似乎苹果使用NSBundleResourceRequest的代码使用了一个dispatch_once块,在其中生成了一个Obj-C异常。我编写了以下测试代码来查看使用dispatch_once块处理异常的行为:

 static dispatch_once_t onceToken;
 @try {

    // 1.) Expected: Caught by first catch block
    // @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Couldn't find" userInfo:nil];

    // 2.) Expected: Caught by second catch block
    // @throw NSInternalInconsistencyException;

    // 3.) Will not be caught be the surrounding @try/@catch block
    dispatch_once(&onceToken, ^{
        @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Couldn't find" userInfo:nil];
    });
} @catch(NSException* e) {
    DDLogError(@"Catch: NSException");
} @catch(id e) {
    DDLogError(@"Catch: Obj-C");
} @catch (...) {
    DDLogError(@"Catch: ...");
}

正如我在评论中所看到的,dispatch_once块内部生成的异常不会在周围的@try/@catch中捕获。
我的问题是:
如何捕获在我没有访问权限的dispatch_once块内生成的异常?
除了不使用苹果的ODR框架之外,有什么措施可以使我的应用程序在这个问题上更加稳定?
附加信息(如果有帮助):
我正在解决的具体堆栈跟踪是以下代码。这不是NSBundleResourceRequest的唯一问题,但所有其他问题都遵循相同的范例。
Application Specific Information:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSBundleResourceRequest could not connect to its helper daemon'

Last Exception Backtrace:
0   CoreFoundation                       0x00000001857f3d38 __exceptionPreprocess + 124
1   libobjc.A.dylib                      0x0000000184d08528 objc_exception_throw + 52
2   Foundation                           0x000000018623e9d0 _setupConnection + 1688
3   libdispatch.dylib                    0x0000000185179048 _dispatch_client_callout + 12
4   libdispatch.dylib                    0x000000018517c710 dispatch_once_f$VARIANT$mp + 56
5   Foundation                           0x000000018623e2e8 +[NSBundleResourceRequest _connection] + 64
6   Foundation                           0x000000018623d1ac -[_NSBundleODRDataForApplications initWithBundle:] + 124
7   Foundation                           0x000000018623d07c +[_NSBundleODRDataForApplications dataForBundle:createIfRequired:] + 180
8   Foundation                           0x000000018623fba0 -[NSBundleResourceRequest conditionallyBeginAccessingResourcesWithCompletionHandler:] + 76

嗨,你有答案了吗? - everettjf
没有,我不确定这是否可能。 - rvijay007
1个回答

0

因为在GCD中运行的块调用

void _dispatch_client_callout(void *ctxt, dispatch_function_t f)
{
    @try {
        return f(ctxt);
    }
    @catch (...) {
        objc_terminate();
    }
}

捕获NSException异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接