Important: The information in this document is obsolete and should not be used for new development.
Using the Exception Manager
The Exception Manager provides a routine that you can use to install an exception handler and remove an exception handler. This section describes how to use this routine and how to write an exception handler.Installing an Exception Handler
You can install an exception handler for your application's context by calling theInstallExceptionHandler
routine. You passInstallExceptionHandler
the address of your exception handler:
prevHandler = InstallExceptionHandler((ExceptionHandler)myHandler);TheInstallExceptionHandler
function replaces any existing exception handler already installed for the current execution context (that is, for the current application) and returns the address of that previously installed handler. Listing 4-1 shows a
routine that installs an exception handler as part of a wrapper around theNewEmptyHandle
function.Listing 4-1 Installing an exception handler
static jump_buf *curJmpBuf; Handle __NewEmptyHandle (ushort trapWord) { Handle returnVal; OSErr myErr; jmp_buf localJump, *oldJump; ExceptionHandler prevHandler; oldJump = curJmpBuf; /*save current jump address*/ curJmpBuf = &localJump; /*install new jump address*/ prevHandler = InstallExceptionHandler((ExceptionHandler)MyHandler); if (myErr = setjmp(localJump)) { LMSetMemErr(theErr); /*set memory error*/ returnVal = 0; /*no bytes allocated*/ } else myErr = c_NewEmptyHandle(&returnVal, trapWord); InstallExceptionHandler(prevHandler); /*restore previous handler*/ curJmpBuf = oldJump; /*restore original jump address*/ return (returnVal); }You can remove the current exception handler from your application's context by passing the valuenil
as the parameter toInstallExceptionHandler
, as follows:
prevHandler = InstallExceptionHandler(nil);Writing an Exception Handler
An exception handler has the following prototype:
typedef OSStatus (*ExceptionHandler) (ExceptionInformation *theException);When your handler is called, the Exception Manager passes it the address of an exception information record, which contains information about the exception, such as its type and the state of the machine at the time the exception occurred. The exception information record is defined by theExceptionInformation
data type.
struct ExceptionInformation { ExceptionKind theKind; MachineInformation *machineState; RegisterInformation *registerImage; FPUInformation *FPUImage; union { MemoryExceptionInformation *memoryInfo; } info; }; typedef struct ExceptionInformation ExceptionInformation;ThetheKind
field contains an exception code. The fieldsmachineState
andregisterImage
contain information about the special-purpose and general-purpose registers, respectively. The values in the special-purpose registers are contained in a machine information record, defined by theMachineInformation
data type.
struct MachineInformation { UnsignedWide CTR; /*Count Register*/ UnsignedWide LR; /*Link Register*/ UnsignedWide PC; /*Program Counter Register*/ unsigned long CR; /*Condition Register*/ unsigned long XER; /*Fixed-Point Exception Register*/ unsigned long MSR; /*Machine State Register*/ }; typedef struct MachineInformation MachineInformation;As you can see, this record contains primarily the values in the special-purpose registers. The values in the general-purpose registers are encoded using a structure of typeRegisterInformation
, which is effectively an array of 32 register values.
Your exception handler can perform any actions necessary or useful for handling the exception. You might attempt to recover from the error or simply terminate your application gracefully. The specific actions you perform depend, of course, on the type
- Note
- For a more detailed description of the exception information record
and its associated data types, see "Data Structures" beginning on page 4-12.
of exception that has occurred. In general, however, you will probably want to use
one or the other of two basic techniques for recovering from the exception.
Listing 4-2 shows a simple exception handler
- Your exception handler might simply transfer control away from the point of execution. For example, you might jump back into your main event loop or into
some error recovery code.- Alternatively, your exception handler might attempt to repair the cause of the excep-
tion by suitably modifying the state of the machine (as reported to your exception handler in an exception information record). You can alter any piece of that machine state, including the PC register. After you have suitably modified the relevant data, your handler should return, passing back a result code. The Exception Manager inspects the result code you return and determines what further actions to take. If you pass backnoErr
, then the Exception Manager restores the machine state to the state contained in the exception information record and resumes execution. If you pass back any other result code, the Operating System proceeds as if the exception had occurred but no exception handler was present.
MyHandler
.Listing 4-2 A native exception handler
OSStatus MyHandler (ExceptionInformation *theException) { if ((theException->theKind >= accessException) && (theException ->theKind <= unresolvablePageFaultException)) longjmp(*curJmpBuf, memWZErr); else return (-1); }As you can see, theMyHandler
exception handler looks for memory-related exceptions and, if it finds any, transfers control by calling thelongjmp
function.
- WARNING
- Returning a value other than
noErr
from your exception handler is likely to cause the current application to be terminated.WARNING
- Your exception handler must be reentrant if it might itself cause any exceptions to be generated. For example, if your exception handler
calls theDebugger
orDebugStr
routine, the trap exception (of typetrapException
) is generated. Normally, a debugger intercepts and handles those kinds of exceptions. If, however, no debugger is installed in the system, your exception handler might be called repeatedly. Eventually, the stack will grow to the lowest memory address, overwriting essential data and causing a system crash.