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

Reply via email to