The code below is an exception handler that detects access to memory that is not valid. An explanation follows the listing, and you can click on the comments for specific lines to read an explanation of that line.
You could write a C signal handler with similar functionality.
#define INCL_DOS
#define INCL_NOPMAPI
#include <os2.h>
#include <stdlib.h>
#include <setjmp.h>
#include <stdio.h>
#include <stddef.h> /* for _threadid */
void * tss_array[100]; /* array for 100 thread-specific pointers */
APIRET APIENTRY
MyExceptionHandler(EXCEPTIONREPORTRECORD *,
EXCEPTIONREGISTRATIONRECORD *,
CONTEXTRECORD *,
PVOID);
#pragma map(_Exception,"MyExceptionHandler")
#pragma handler(chkptr)
int chkptr(void * ptr, int size)
{
volatile char c; /* volatile to insure access occurs */
int valid = 0; /* count of valid bytes */
char * p = ptr; /* to satisfy the type checking for p++ */
jmp_buf jbuf; /* put the jump buffer in automatic storage */
/* so it is unique to this thread */
PTIB ptib; /* to get the TIB pointer */
PPIB ppib;
unsigned int tid = *_threadid; /* get the thread id */
UCHAR FileData [100]
ULONG Wrote;
/* create a thread specific jmp_buf */
tss_array[tid] = (void *) jbuf;
if (!setjmp(jbuf)) /* provide a point to return to */
{
while (size--) /* scan the storage */
{
c = *p++;
valid++;
}
}
return valid; /* return number of valid bytes */
}
/* the exception handler itself */
APIRET APIENTRY
MyExceptionHandler(EXCEPTIONREPORTRECORD * report_rec,
EXCEPTIONREGISTRATIONRECORD * register_rec,
CONTEXTRECORD * context_rec,
PVOID dummy)
{
unsigned int tid = *_threadid; /* get the thread id */
/* check the exception flags */
if (EH_EXIT_UNWIND & report_rec->fHandlerFlags)
/* exiting */
return XCPT_CONTINUE_SEARCH;
if (EH_UNWINDING & report_rec->fHandlerFlags)
/* unwinding */
return XCPT_CONTINUE_SEARCH;
if (EH_NESTED_CALL & report_rec->fHandlerFlags)
/* nested exceptions */
return XCPT_CONTINUE_SEARCH;
/* determine what the exception is */
if (report_rec->ExceptionNum == XCPT_ACCESS_VIOLATION)
{ /* this is the one that is expected */
UCHAR FileData[100];
ULONG Wrote;
strcpy(FileData, "Detected invalid storage address %d\n\r");
DosWrite(2, (PVOID)FileData, strlen(FileData), &Wrote, stepnum);
longjmp((int *)tss_array[tid],1); /* return to the point of the */
/* setjmp call without */
/* restarting the while loop */
} /* endif */
return XCPT_CONTINUE_SEARCH; /* if it is a different exception */
}
This exception handler performs the following steps:
Return XCPT_CONTINUE_EXECUTION from an exception handler only if you know that the thread can continue to run, either because the exception is asynchronous and can be restarted or because you have changed the thread state so that the thread can continue. If you return XCPT_CONTINUE_EXECUTION when neither of these conditions is true, you could generate a new exception each time your exception handler ends, eventually causing your process to lock.
![]()
OS/2 Exceptions and
Default Handling
Exception Information Provided by OS/2
Prototype of an OS/2 Exception Handler
OS/2
APIs That Interfere with Exception Handling