Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: PowerPC System Software /
Chapter 4 - Exception Manager


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 the InstallExceptionHandler routine. You pass InstallExceptionHandler the address of your exception handler:

prevHandler = InstallExceptionHandler((ExceptionHandler)myHandler);
The InstallExceptionHandler 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 the NewEmptyHandle 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 value nil as the parameter to InstallExceptionHandler, 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 the ExceptionInformation data type.

struct ExceptionInformation {
   ExceptionKind                    theKind;
   MachineInformation               *machineState;
   RegisterInformation              *registerImage;
   FPUInformation                   *FPUImage;
   union {
      MemoryExceptionInformation    *memoryInfo;
   } info;
};
typedef struct ExceptionInformation ExceptionInformation;
The theKind field contains an exception code. The fields machineState and registerImage 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 the MachineInformation 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 type RegisterInformation, which is effectively an array of 32 register values.

Note
For a more detailed description of the exception information record
and its associated data types, see "Data Structures" beginning on page 4-12.
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
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 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, the MyHandler exception handler looks for memory-related exceptions and, if it finds any, transfers control by calling the longjmp 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 the Debugger or DebugStr routine, the trap exception (of type trapException) 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.

Previous Book Contents Book Index Next

© Apple Computer, Inc.
3 JUL 1996