NSExceptionHandler - What is a "top-level" vs. "other" exception?
NSExceptionHandler - What is a "top-level" vs. "other" exception?
- Subject: NSExceptionHandler - What is a "top-level" vs. "other" exception?
- From: James Farwell <email@hidden>
- Date: Fri, 11 Nov 2011 15:31:29 -0800
Hey all,
I have an application in which I would like to do special handling of
exceptions that are "uncaught" by my code (as in they reach NSApplication's
exception handler on the main thread or the uncaught exception handler if
not on the main thread). However, if my code catches the exception with a
@try/@catch block, then I would like that @catch block to handle the
exception first, and then only if it re-throws should it hit my special
handling.
I believed that NSExceptionHandler would allow me to do exactly this.
According to its documentation, setting its mask to contain
"NSHandleTopLevelExceptionMask" should cause it to handle exceptions that
will be caught by the "top-level handler," and furthermore that "In the
main thread of a Cocoa application, the top-level handler is the global
NSApplication instance." There is a separate mask,
"NSHandleOtherExceptionMask," which claims it covers exceptions caught by
"handlers lower than the top-level handler." They way I understand this
is: if I set the mask on NSExceptionHandler to
"(NSHandleUncaughtExceptionMask | NSHandleTopLevelExceptionMask)" then any
exception thrown outside of a @try/@catch block should be handled by
NSExceptionHandler, but exceptions thrown inside a @try/@catch block should
be ignored.
However, when I tried this, exceptions thrown outside of a @try/@catch
block were not being seen by NSExceptionHandler at all. So I wrote the
following code in an otherwise fresh XCode project:
--- snip ---
@interface TestExceptionHandlerDelegate : NSObject
- (BOOL)exceptionHandler:(NSExceptionHandler *)sender
shouldHandleException:(NSException *)exception
mask:(NSUInteger)aMask;
@end
@implementation TestExceptionHandlerDelegate
- (BOOL)exceptionHandler:(NSExceptionHandler *)sender
shouldHandleException:(NSException *)exception
mask:(NSUInteger)aMask
{
NSLog(@"Exception handler handling exception %@ because of mask %lu",
exception, aMask);
return YES;
}
@end
@implementation TestAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSExceptionHandler *handler = [NSExceptionHandler
defaultExceptionHandler];
[handler setExceptionHandlingMask:NSLogAndHandleEveryExceptionMask];
[handler setDelegate:[[TestExceptionHandlerDelegate alloc] init]];
@try {
[[NSException exceptionWithName:@"TestCaughtException" reason:@"Caught
Test" userInfo:nil] raise];
}
@catch (NSException *exception) {
NSLog(@"Local @catch block caught exception %@", exception);
}
[[NSException exceptionWithName:@"TestUncaughtException" reason:@"Uncaught
Test" userInfo:nil] raise];
}
@end
--- snip ---
The resulting log output is:
--- snip ---
2011-11-09 16:01:14.553 Test[1725:60b] NSExceptionHandler has recorded the
following exception:
TestCaughtException -- Caught Test
Stack trace: 0x100005c69 0x7fff8f863d5e 0x7fff8ccbb4c9 0x10000149d
0x7fff9048ade2 0x7fff8cbd9e0a 0x7fff90477097 0x7fff90863aa7
0x7fff9086380d 0x7fff908624d2 0x7fff90862233 0x7fff8cc23851
0x7fff904ad89b 0x7fff904ac822 0x7fff904ac6b0 0x7fff8966fc25
0x7fff8966fb03 0x7fff8966f9f7 0x7fff85667b6d 0x7fff9085f63d
0x7fff9085ecf5 0x7fff9085b62d 0x7fff90ada80c 0x100001382 0x100001354
0x1
2011-11-09 16:01:14.554 Test[1725:60b] Exception handler handling exception
Caught Test because of mask 512
2011-11-09 16:01:14.577 Test[1725:60b] Local @catch block caught exception
Caught Test
2011-11-09 16:01:14.577 Test[1725:60b] NSExceptionHandler has recorded the
following exception:
TestUncaughtException -- Uncaught Test
Stack trace: 0x100005c69 0x7fff8f863d5e 0x7fff8ccbb4c9 0x1000014e2
0x7fff9048ade2 0x7fff8cbd9e0a 0x7fff90477097 0x7fff90863aa7
0x7fff9086380d 0x7fff908624d2 0x7fff90862233 0x7fff8cc23851
0x7fff904ad89b 0x7fff904ac822 0x7fff904ac6b0 0x7fff8966fc25
0x7fff8966fb03 0x7fff8966f9f7 0x7fff85667b6d 0x7fff9085f63d
0x7fff9085ecf5 0x7fff9085b62d 0x7fff90ada80c 0x100001382 0x100001354
0x1
2011-11-09 16:01:14.578 Test[1725:60b] Exception handler handling exception
Uncaught Test because of mask 512
--- snip ---
So, both exceptions, are being handled under the mask 512 aka 1 << 9, which
is NSHandleOtherExceptionMask.
My question is then: what did I misunderstand about NSExceptionHandler's
documentation? Isn't the exception being raised outside of a a @try/@catch
block going to be caught by NSApplication which is, according to the
documentation, the "top-level" handler? Why is it being considered an
"other" exception instead of a "top-level" exception?
If NSHandleTopLevelExceptionMask doesn't handle this case, what does it
handle?
Thanks!
- James
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden