mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Fix buggy behavior where if the uncaught exception handler was set to a
function which returned, the -raise method could return. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21389 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
20887bf59c
commit
a7f1ff64f9
3 changed files with 85 additions and 35 deletions
|
@ -1,3 +1,11 @@
|
|||
2005-07-01 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSException.m: ([-raise]) Fix behavior to be the same as in
|
||||
MacOS-X (ie call the default uncaught exception handler after
|
||||
whatever handler is set, in case the set handler does not terminate).
|
||||
Ensures that the -raise method cannot return.
|
||||
* Testing/basic.m: Add test for uncaught exception handler.
|
||||
|
||||
2005-06-30 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSSerializer.m: deserializeFromInfo() check that cross
|
||||
|
|
|
@ -79,36 +79,17 @@ NSString* const NSParseErrorException
|
|||
|
||||
#include "GSPrivate.h"
|
||||
|
||||
static void
|
||||
_preventRecursion (NSException *exception)
|
||||
static void _terminate()
|
||||
{
|
||||
fprintf(stderr, "recursion encountered handling uncaught exception\n");
|
||||
fflush(stderr); /* NEEDED UNDER MINGW */
|
||||
}
|
||||
|
||||
static void
|
||||
_NSFoundationUncaughtExceptionHandler (NSException *exception)
|
||||
{
|
||||
BOOL a;
|
||||
extern const char* GSArgZero(void);
|
||||
|
||||
_NSUncaughtExceptionHandler = _preventRecursion;
|
||||
#if 1
|
||||
fprintf(stderr, "%s: Uncaught exception %s, reason: %s\n", GSArgZero(),
|
||||
[[exception name] lossyCString], [[exception reason] lossyCString]);
|
||||
fflush(stderr); /* NEEDED UNDER MINGW */
|
||||
#else
|
||||
NSLog("Uncaught exception %@, reason: %@",
|
||||
[exception name], [exception reason]);
|
||||
#endif
|
||||
BOOL shouldAbort;
|
||||
|
||||
#ifdef DEBUG
|
||||
a = YES; // abort() by default.
|
||||
shouldAbort = YES; // abort() by default.
|
||||
#else
|
||||
a = NO; // exit() by default.
|
||||
shouldAbort = NO; // exit() by default.
|
||||
#endif
|
||||
a = GSEnvironmentFlag("CRASH_ON_ABORT", a);
|
||||
if (a == YES)
|
||||
shouldAbort = GSEnvironmentFlag("CRASH_ON_ABORT", shouldAbort);
|
||||
if (shouldAbort == YES)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
@ -118,6 +99,18 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_NSFoundationUncaughtExceptionHandler (NSException *exception)
|
||||
{
|
||||
extern const char* GSArgZero(void);
|
||||
|
||||
fprintf(stderr, "%s: Uncaught exception %s, reason: %s\n", GSArgZero(),
|
||||
[[exception name] lossyCString], [[exception reason] lossyCString]);
|
||||
fflush(stderr); /* NEEDED UNDER MINGW */
|
||||
|
||||
_terminate();
|
||||
}
|
||||
|
||||
/**
|
||||
<p>
|
||||
The <code>NSException</code> class helps manage errors in a program. It
|
||||
|
@ -223,25 +216,56 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
|||
Raises the exception. All code following the raise will not be
|
||||
executed and program control will be transfered to the closest
|
||||
calling method which encapsulates the exception code in an
|
||||
NS_DURING macro, or to the uncaught exception handler if there is no
|
||||
other handling code.
|
||||
NS_DURING macro.<br />
|
||||
If the exception was not caught in a macro, the currently set
|
||||
uncaught exception handler is called to perform final logging
|
||||
and handle program termination.<br />
|
||||
If the uncaught exception handler fails to terminate the program,
|
||||
then the default builtin uncaught exception handler will do so.<br />
|
||||
NB. all other exception raising methods call this one, so if you
|
||||
want to set a breakpoint when debugging, set it in this method.
|
||||
*/
|
||||
- (void) raise
|
||||
{
|
||||
NSThread *thread;
|
||||
NSHandler *handler;
|
||||
|
||||
if (_NSUncaughtExceptionHandler == NULL)
|
||||
{
|
||||
_NSUncaughtExceptionHandler = _NSFoundationUncaughtExceptionHandler;
|
||||
}
|
||||
|
||||
thread = GSCurrentThread();
|
||||
handler = thread->_exception_handler;
|
||||
if (handler == NULL)
|
||||
{
|
||||
_NSUncaughtExceptionHandler(self);
|
||||
return;
|
||||
static BOOL recursion = NO;
|
||||
|
||||
/*
|
||||
* Set a flag to prevent recursive uncaught exceptions.
|
||||
*/
|
||||
if (recursion == NO)
|
||||
{
|
||||
recursion = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"recursion encountered handling uncaught exception\n");
|
||||
fflush(stderr); /* NEEDED UNDER MINGW */
|
||||
_terminate();
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the uncaught exception handler (if there is one).
|
||||
*/
|
||||
if (_NSUncaughtExceptionHandler != NULL)
|
||||
{
|
||||
(*_NSUncaughtExceptionHandler)(self);
|
||||
}
|
||||
|
||||
/*
|
||||
* The uncaught exception handler which is set has not
|
||||
* exited, so we call the builtin handler, (undocumented
|
||||
* behavior of MacOS-X).
|
||||
* The standard handler is guaranteed to exit/abort.
|
||||
*/
|
||||
_NSFoundationUncaughtExceptionHandler(self);
|
||||
}
|
||||
|
||||
thread->_exception_handler = handler->next;
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
|
||||
#if 1
|
||||
|
||||
static void uncaught(NSException* e)
|
||||
{
|
||||
fprintf(stderr, "In uncaught exception handler.\n");
|
||||
[NSException raise: NSGenericException format: @"Recursive exception"];
|
||||
}
|
||||
|
||||
static void test1(void)
|
||||
{
|
||||
NSURL *baseURL = [NSURL fileURLWithPath:@"/usr/local/bin"];
|
||||
|
@ -138,7 +144,15 @@ int main ()
|
|||
|
||||
printf ("Hello from object at 0x%x\n", (unsigned)[o self]);
|
||||
|
||||
NSLog(@"Value for foo is %@", [a valueForKey: @"foo"]);
|
||||
NS_DURING
|
||||
{
|
||||
NSLog(@"Value for foo is %@", [a valueForKey: @"foo"]);
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"Caught expected exception: %@", localException);
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
|
||||
[o release];
|
||||
o = [NSString stringWithFormat: @"/proc/%d/status", getpid()];
|
||||
|
@ -146,6 +160,10 @@ int main ()
|
|||
o = [NSString stringWithContentsOfFile: o];
|
||||
NSLog(@"'%@'", o);
|
||||
|
||||
NSLog(@"This test should now cause program termination after a recursive exception");
|
||||
|
||||
NSSetUncaughtExceptionHandler(uncaught);
|
||||
[NSException raise: NSGenericException format: @"an artifical exception"];
|
||||
exit (0);
|
||||
}
|
||||
#else
|
||||
|
|
Loading…
Reference in a new issue