When dealing with Apple's On-Demand Resource framework, my app is finding many exceptions being generated for a subset of users. My first attempt at fixing this was to wrap my code within an @try/@catch block, but unfortunately, the crashes still propagated. I've narrowed down the issue, but am unsure how to solve it. It seems that Apple's code for using NSBundleResourceRequest uses a dispatch_once block, inside which an Obj-C exception is generated. I wrote the following test code to see the behavior of exception handling with a dispatch_once block:
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: ...");
}
As seen in my comments, the exception generated within a dispatch_once block doesn't get caught in the surrounding @try/@catch.
My questions are:
How can I catch an exception generated within a dispatch_once block whose source code (Apple's) I don't have access to?
Is there anything I can do to make my app more stable with regards to this issue, besides not using Apple's ODR framework?
Additional Information (if it helps):
The concrete stack trace I'm trying to solve for is the following code. This is not the only issue with the NSBundleResourceRequest, but all the other issues follow the same paradigm.
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