Obj-C Exceptions In Gecko: Difference between revisions

no edit summary
No edit summary
Line 3: Line 3:
See [https://bugzilla.mozilla.org/show_bug.cgi?id=163260 bug 163260].
See [https://bugzilla.mozilla.org/show_bug.cgi?id=163260 bug 163260].


== Gecko 1.8 ==
The basic problem we have is that almost every call into Apple's framework (C or Obj-C) could potentially throw an Obj-C exception and unwind our stack with nasty consequences. Sometimes the browser crashes, sometimes it just appears to have lost its mind, and theoretically there could be security consequences. This is because we have no handlers in place now and as the stack unwinds code gets skipped and C++ temporary objects do not get their destructors run.
Since there isn't a whole lot of code that's using Cocoa in Gecko 1.8, it might be best to to write macros to wrap any XPCOM entry point that calls cocoa, start to finish. NS_OBJC_EXCEPTION_CATCHER_START and _END, for example.


Another, eviler approach is to override NSException's initWithName:reason:userInfo: method to instead call some sort of assertion, and then return nil. This of course bypasses the entire ObjC exception system, and will horribly, horribly break any code that depends upon actually handling ObjC exceptions. There might still some merit in the idea of posing as NSException, perhaps to override -raise?
You can read more about it in the bug, but the conclusion we came to is that we need to wrap all calls into Apple frameworks with Obj-C exception handlers.


== Gecko 1.9 ==
I have checked in a set of macros for doing that, see this file:


Mac OS X 10.3 brought new exception handling support. It's possible that setjmp and longjmp may no longer be  used for some parts of the exception system, which now appears to be in the compiler, at least partially. Some parts of the exception handling are still using  setjmp/longjmp, obviously, because stack smashing is still occurring. Need to look into exactly what's safe and what's not. We may end up in the same boat as on branch, unfortunately.
mozilla/xpcom/base/nsObjCExceptions.h


As far as I've seen, Apple documents what exceptions can get thrown. We really should just exit the browser with a nonzero exit code when we catch an unhandled ObjC exception. --[[User:Cbarrett|Cbarrett]] 15:33, 14 September 2007 (PDT)
Before you start doing anything, please read through every line of that file and make sure you understand what all of it is for. If you don't understand anything please ask me on email or irc. It wouldn't be very awesome if you posted a bunch of work and had to do it all over again.


== setjmp/longjmp not entirely fatal? ==
Another thing to read over is nsAppShell.mm. I have done the work for nsAppShell.mm already and checked it in. Make sure you understand why I made the choices I did there, and again ask if you are unclear about anything.
It should be noted that as long as the stack is able to be unwound properly once we return to C++, things should be OK. It's still unclear why the crashes are happening in the first place, so perhaps a different NSExceptionHandler mask, using an NSExceptionHandler delegate, or calling NSSetUncaughtExceptionHandler will allow us to handle ObjC exceptions in a more graceful manner.
 
When wrapping calls in a method, the first choice you'll have to make is whether to wrap specific calls or the whole method impl. Which one you pick is usually a matter of cleanliness. If there is a big method with a single Apple framework call in it, you might just want to wrap that specific call. Your choice of macros are these:
 
NS_OBJC_TRY_IGNORE
NS_OBJC_TRY_ABORT
 
NS_OBJC_TRY_EXPR_NULL
NS_OBJC_TRY_EXPR_ABORT
 
The ones that contain EXPR are for expressions - for example:
 
foo = NS_OBJC_TRY_EXPR_ABORT([bar doSomething]);
 
They wrap an expression that returns a value. The other macros don't. They'd be for something like this:
 
NS_OBJC_TRY_ABORT([bar doSomething]);
 
The macros that include ABORT will kill the app if they catch an exception, you will almost always want to use these. It saves a lot of time if we don't have to think about recovery strategies for calls. In order to code for recovery you'd have to understand something about the context of the code you are working in. If we start seeing exceptions killing the app it'll be easy to go back and code the calls that are throwing for recovery. That probably won't happen and if it does it'll probably be just 1-2 calls we need to not abort on.
 
More coming...
- block macros
- identifying apple framework calls
- non-.mm files
- whitespace
- including nsObjCExceptions.h
 
-Josh Aas
Confirmed users, Bureaucrats and Sysops emeriti
1,680

edits