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 (Cocoa-dev@lists.apple.com) 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com