An application uses DosSetExceptionHandler to register its own exception handling routines. More than one routine can be registered; the last routine registered will be called first.
One or more exception handlers can be registered for each thread in a process. Moreover, exception handlers can be specified not only for system exceptions, but also for user-defined exceptions that are anticipated for a particular thread.
Only Process Termination exceptions are sent to all threads in a process. Other exceptions (synchronous exceptions) are sent only to the exception handler registered for the thread where the exception occurred. The application must register an exception handler for each thread that is handling exceptions.
The following code fragment shows how an application registers an exception handling routine:
#define INCL_BASE #define INCL_DOSEXCEPTIONS #include <os2.h> ULONG _System myHandler(PEXCEPTIONREPORTRECORD, PEXCEPTIONREGISTRATIONRECORD, PCONTEXTRECORD, PVOID); VOID main(VOID) { EXCEPTIONREGISTRATIONRECORD xcpthand = { 0, &myHandler }; DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR); DosSetExceptionHandler(&xcpthand); /* . . Other processing occurs here; myHandler will handle the exceptions. . */ DosUnsetExceptionHandler(&xcpthand); }
If a procedure registers an exception handler, it must deregister the handler by calling DosUnsetExceptionHandler before returning.
Note:
A procedure must not call DosSetExceptionHandler if it performs language-specific exception or unwind handling. This restriction is not enforced, but unpredictable results could occur if it is violated.
DosSetExceptionHandler and DosUnsetExceptionHandler provide the portable means of implementing exception handlers. The non-portable approach is taken by directly manipulating the exception handler chain. High level languages generate code that abides by this restriction. Assembly language programmers must assume responsibility for verifying that handler registration and deregistration occur correctly.
EXCEPTIONREGISTRATIONRECORD must be created on the application's stack. That is, it must be local to the routine that registers the exception handler, rather than a global variable. It cannot be stored in the data segment of the program.
Note that in the code fragment above, the declaration is placed inside the braces (see figure below). Therefore xcpthand is local to the main() routine and is stored on the program's stack.
EXCEPTIONREGISTRATIONRECORD xcpthand = { 0, &myHandler };