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:
Richard Frith-Macdonald 2005-07-01 08:53:32 +00:00
parent 20887bf59c
commit a7f1ff64f9
3 changed files with 85 additions and 35 deletions

View file

@ -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;