Signal and Exception Handling
Considerations
Considerations when registering
a signal handler:
- You can register any function as a signal
handler. Make sure you are registering a valid function.
- If your signal handler resides in a DLL,
ensure that you change the signal handler when you unload
the DLL. You will see no warnings or error messages if
you unload the DLL without changing the handler, but your
program will probably terminate the next time the handler
is called. If another DLL has been loaded in the same
address range, your program may continue but with
undefined results.
- The SIGILL signal is not guaranteed to
occur when you call an invalid function using a pointer.
If the pointer points to a valid instruction stream,
SIGILL is not raised.
Considerations when writing
a signal handler:
- Your signal handler may call any
non-critical C library functions, but not any critical functions . This is because critical functions are not
reentrant. If such a function is on the stack at the time
of the signal, reentering it may cause odd side effects
or make your program fail.
- Your signal handler should not assume that
SIGSEGV always implies an invalid data pointer. Other
events, such as an address pointer to outside of your
code segment, can raise this signal.
- The SIGILL signal is not guaranteed to
occur when you call an invalid function using a pointer.
If the pointer points to a valid instruction stream,
SIGILL is not raised.
- When you call longjmp to leave a signal
handler, be sure that the buffer you are jumping to was
created by the thread that you are in. Do not call setjmp
from one thread and longjmp from another. The IBM C and
C++ Compilers library terminates a process where such a
call is made.
To protect internal data structures on OS/2,
some library code is placed in must-complete sections.
When a signal occurs, the library waits until such a
section ends before it reports the signal. You can use
the OS/2 API DosEnterMustComplete to create must-complete
sections in your own code.
- Declare variables referenced by both the
signal handler and by other code to be volatile, to
ensure they are always updated when they are referenced.
Because the ANSI draft of the C++ language
does not specify the behavior of a throw statement in a
signal handler, the most portable way to ensure that the
appropriate destructors are called is to add statements
to the setjmp location that will do a throw if necessary.
- If a file I/O routine from <stdio.h>
is taking input from the console when an asynchronous
signal (SIGINT,
SIGBREAK, or SIGTERM) occurs, the
behavior depends on whether a signal handler is
registered. If no handler is registered, the input stream
is terminated and the default signal action is taken. If
a handler is registered, entry to the handler is deferred
until the library routine returns.
Do not use a C++ throw to exit a signal
handler for signals SIGINT, SIGTERM, and SIGBREAK. When
the signal is asynchronous, stack layout at the time of
the signal may not permit clean stack unwind by the C++
exception handler code.
Considerations when writing exceptions
- Keep your exception handler simple and
specific. Exception handlers are easier to write and
maintain if you limit what they can do. Also, include a
#pragma handler statement in every function in your
executable module that can be called from a DLL. This
directive generates the code to register the exception
handler before the function runs, and to remove the
exception handler when the function ends.
- Check for and handle only the exceptions
that you expect to encounter, and allow the default
exception handler to handle the unexpected. If the
operating system adds new exceptions, or if you create
your own, the default handler will handle them.
- Always check the exception flags to
determine how the exception occurred. Any exception
handler can be unwound by a subsequent handler.
- If you are using semaphores and an
exception occurs while your code owns a semaphore, you
must ensure that the semaphore is released. You can
release the semaphore either by continuing the excecution
or by explicitly releasing the semaphore in the signal
handler.
- Your exception handler receives the
exception registration record when an exception occurs.
Do not use the return address of the calling function to
tell the handler where to resume execution, because the
values of the registers other than EBP (for example, EBX,
EBI, and EDI) at the return are generally not available
to your exception handler.
- You need approximately 1.5K of stack
remaining for the operating system to be able to call
your exception handler. If you do not have enough stack
left, the operating system terminates your process.
- The IBM C and C++ Compilers default
exception handler is not available in the subsystem
libraries.
Avoid using restricted OS/2 APIs
because they can interfere with IBM C and C++ Compilers
default exception handling.

C++ Exception Handling Overview
Signals
and Exceptions
Signal
and Exception Handling
Calling
Conventions

Critical Functions