Exceptions


#1

Hey Julian, for masochists like me who are mixing cocoa and juce would you consider the following?

This’ll catch any appkit exceptions and give me a chance to log them.

[code]
void MessageManager::runDispatchLoop()
{
if (! quitMessagePosted) // check that the quit message wasn’t already posted…
{
const ScopedAutoReleasePool pool;

    // must only be called by the message thread!
    jassert (isThisTheMessageThread());
	@try {
		[NSApp run];
	}
	@catch (NSException * e) {
		// called if AppKit throws an exception.
		// application will exit after this...but at least you have a chance to log the exception.
		// We will always have a JUCEApplication instance...
		std::runtime_error ex(std::string("Appkit/Cocoa exception. Name:") + [[e name]UTF8String] + " Reason:" + [[e reason]UTF8String] );
		JUCEApplication::getInstance()->unhandledException (&ex, __FILE__, __LINE__);
	}
	@finally {
		
	}
	
}

}[/code]

If you want to test, throw this in a .mm function that the main runloop can call into…
[[NSException exceptionWithName:@“Exception Name” reason:@“Exception Reason” userInfo:nil]raise];
or
[NSDictionary dictionaryWithObject:nil forKey:@“CRASH!”];
(gives me at least this…)


#2

That’s a really good suggestion - thanks!


#3

This looks useful too…

http://www.codeshorts.ca/2008/jul/03/getting-a-de-mangled-c-stack-trace-from-an-nsexcep

EDIT : execinfo.h is in 10.5 + only


#4

Thanks for adding that to the tip.

I have another suggestion to sort of “recover” from the exception, but I don’t really know if its a good idea… The comment is from Apple’s dev site, which certainly makes it sound like we should exit, but then again some stuff can be recovered from like unrecognized selectors… ie. accidentally sending isEqualToString: to an NSNumber

but perhaps those should be “caught” elsewhere.

[code]void MessageManager::runDispatchLoop()
{
if (! quitMessagePosted) // check that the quit message wasn’t already posted…
{
const ScopedAutoReleasePool pool;

    // must only be called by the message thread!
    jassert (isThisTheMessageThread());

#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
#if JUCE_DEBUG
/* The Cocoa frameworks are generally not exception-safe.
The general pattern is that exceptions are reserved for programmer error only, and the program catching such an exception should quit soon afterwards.*/

	while (!quitMessagePosted)

#endif
{
@try
{
[NSApp run];
}
@catch (NSException* e)
{
// An AppKit exception will kill the app, but at least this provides a chance to log it.,
std::runtime_error ex (std::string ("NSException: ") + [[e name] UTF8String] + “, Reason:” + [[e reason] UTF8String]);
JUCEApplication::sendUnhandledException (&ex, FILE, LINE);
}
@finally
{

		}
	}

#else
[NSApp run];
#endif
}
}[/code]

Happy Holidays to all


#5

hmm, I think I’d rather leave it to crash…


#6