cocoa - Why is raising an NSException not bringing down my application? -
the problem
i'm writing cocoa application , want raise exceptions crash application noisily.
i have following lines in application delegate:
[nsexception raise:nsinternalinconsistencyexception format:@"this should crash application."]; abort();
the problem is, don't bring down application - message logged console , app carries on it's merry way.
as understand it, whole point of exceptions they're fired under exceptional circumstances. in these circumstances, want application quit in obvious way. , doesn't happen.
what i've tried
i've tried:
-(void)applicationdidfinishlaunching:(nsnotification *)note // ... [self performselectoronmainthread:@selector(crash) withobject:nil waituntildone:yes]; } -(void)crash { [nsexception raise:nsinternalinconsistencyexception format:@"this should crash application."]; abort(); }
which doesn't work ,
-(void)applicationdidfinishlaunching:(nsnotification *)note // ... [self performselectorinbackground:@selector(crash) withobject:nil]; } -(void)crash { [nsexception raise:nsinternalinconsistencyexception format:@"this should crash application."]; abort(); }
which, rather confusingly, works expected.
what's going on? doing wrong?
update - nov 16, 2010: there issues answer when exceptions thrown inside ibaction methods. see answer instead:
how can stop hitoolbox catching exceptions?
this expands on david gelhar's answer, , link provided. below how did overriding nsapplication's -reportexception:
method. first, create exceptionhandling category nsapplication (fyi, should add 2-3 letter acronym before "exceptionhandling" reduce risk of name clashing):
nsapplication+exceptionhandling.h
#import <cocoa/cocoa.h> @interface nsapplication (exceptionhandling) - (void)reportexception:(nsexception *)anexception; @end
nsapplication+exceptionhandling.m
#import "nsapplication+exceptionhandling.h" @implementation nsapplication (exceptionhandling) - (void)reportexception:(nsexception *)anexception { (*nsgetuncaughtexceptionhandler())(anexception); } @end
second, inside nsapplication's delegate, did following:
appdelegate.m
void exceptionhandler(nsexception *anexception) { nslog(@"%@", [anexception reason]); nslog(@"%@", [anexception userinfo]); [nsapp terminate:nil]; // can call exit() instead if desired } - (void)applicationwillfinishlaunching:(nsnotification *)anotification { nssetuncaughtexceptionhandler(&exceptionhandler); // additional code... // note: see "update" @ end of post regarding possible glitch here... }
rather use nsapp's terminate:
, can call exit()
instead. terminate:
more cocoa-kosher, though may want skip applicationshouldterminate:
code in event exception thrown , hard-crash exit()
:
#import "sysexits.h" // ... exit(ex_software);
whenever exception thrown, on main thread, , it's not caught , destroyed, custom uncaught exception handler called instead of nsapplication's. allows crash application, among other things.
update:
there appears small glitch in above code. custom exception handler won't "kick in" , work until after nsapplication has finished calling of delegate methods. means if setup-code inside applicationwillfinishlaunching: or applicationdidfinishlaunching: or awakefromnib:, default nsapplication exception handler appears in-play until after it's initialized.
what means if this:
- (void)applicationwillfinishlaunching:(nsnotification *)anotification { nssetuncaughtexceptionhandler(&exceptionhandler); myclass *myclass = [[myclass alloc] init]; // throws exception during init... }
your exceptionhandler won't exception. nsapplication will, , it'll log it.
to fix this, put initialization code inside @try/@catch/@finally
block , can call custom exceptionhandler:
- (void)applicationwillfinishlaunching:(nsnotification *)anotification { nssetuncaughtexceptionhandler(&exceptionhandler); @try { myclass *myclass = [[myclass alloc] init]; // throws exception during init... } @catch (nsexception * e) { exceptionhandler(e); } @finally { // cleanup code... } }
now exceptionhandler()
gets exception , can handle accordingly. after nsapplication has finished calling delegate methods, nsapplication+exceptionhandling.h category kicks in, calling exceptionhandler() through custom -reportexception:
method. @ point don't have worry @try/@catch/@finally when want exceptions raise uncaught exception handler.
i'm little baffled causing this. behind-the-scenes in api. occurs when subclass nsapplication, rather adding category. there may other caveats attached well.
Comments
Post a Comment