exc_handle, exc_unhandle, exc_bound, exc_notify, exc_raise,
exc_on_exit, exc_uniqpatt - LWP exception handling
int exc_handle(pattern, func, arg)
caddr_t (*exc_bound(pattern, arg))()
int exc_on_exit(func, arg)
These primitives can be used to manage exceptional conditions in a
thread. Basically, raising an exception is a more general form of non-
local goto or longjmp, but the invocation is pattern-based. It is also
possible to notify an exception handler whereby a function supplied by
the exception handler is invoked and control is returned to the raiser
of the exception. Finally, one can establish a handler which is always
invoked upon procedure exit, regardless of whether the procedure exits
using a return or an exception raised to a handler established prior to
the invocation of the exiting procedure.
exc_handle() is used to establish an exception handler. exc_handle()
returns 0 to indicate that a handler has been established. A return of
-1 indicates an error in trying to establish the exception handler. If
it returns something else, an exception has occurred and any procedure
calls deeper than the one containing the handler have disappeared. All
exception handlers established by a procedure are automatically dis-
carded when the procedure terminates.
exc_handle() binds a pattern to the handler, where a pattern is an
integer, and two patterns match if their values are equal. When an
exception is raised with exc_raise(), the most recent handler that has
established a matching pattern will catch the exception. A special
pattern (CATCHALL) is provided which matches any exc_raise() pattern.
This is useful for handlers which know that there is no chance the
resources allocated in a routine can be reclaimed by previous routines
in the call chain.
The other two arguments to exc_handle() are a function and an argument
to that function. exc_bound() retrieves these arguments from an
exc_handle() call made by the specified thread. By using exc_bound()
to retrieve and call a function bound by the exception handler, a pro-
cedure can raise a notification exception which allows control to
return to the raiser of the exception after the exception is handled.
exc_raise() allows the caller to transfer control (do a non-local goto)
to the matching exc_handle(). This matching exception handler is
destroyed after the control transfer. At this time, it behaves as if
exc_handle() returns with the pattern from exc_raise() as the return
value. Note: func of exc_handle() is not called using exc_raise() --
it is only there for notification exceptions. Because the exception
handler returns the pattern that invoked it, it is possible for a han-
dler that matches the CATCHALL pattern to reraise the exact exception
it caught by using exc_raise() on the caught pattern. It is illegal to
handle or raise the pattern 0 or the pattern -1. Handlers are searched
for pattern matches in the reverse execution order that they are set
(i.e., the most recently established handler is searched first).
exc_unhandle() destroys the most recently established exception handler
set by the current thread. It is an error to destroy an exit-handler
set up by exc_on_exit(). When a procedure exits, all handlers and exit
handlers set in the procedure are automatically deallocated.
exc_notify() is a convenient way to use exc_bound. The function which
is bound to pattern is retrieved. If the function is not NULL, the
function is called with the associated argument and the result is
returned. If the function is NULL, exc_raise(pattern) is returned.
exc_on_exit() specifies an exit procedure and argument to be passed to
the exit procedure, which is called when the procedure which sets an
exit handler using exc_on_exit() exits. The exit procedures (more than
one may be set) will be called regardless if the setting procedure is
exited using a return or an exc_raise(). Because the exit procedure is
called as if the handling procedure had returned, the argument passed
to it should not contain addresses on the handler's stack. However,
any value returned by the procedure which established the exit proce-
dure is preserved no matter what the exit procedure returns. This
primitive is used in the MONITOR macro to enforce the monitor disci-
pline on procedures.
Some signals can be considered to be synchronous traps. They are usu-
ally the starred (*) signals in the signal(3V) man pages. These are:
SIGSYS, SIGBUS, SIGEMT, SIGFPE, SIGILL, SIGTRAP, SIGSEGV. If an event
is marked as a trap using agt_trap() (see agt_create(3L)) the event
will generate exceptions instead of agent messages. This mapping is
per-pod, not per-thread. A thread which handles the signal number of
one of these as the pattern for exc_handle() will catch such a signal
as an exception. The exception will be raised as an exc_notify() so
either escape or notification style exceptions can be used, depending
on what the matching exc_handle() provides. If the exception is not
handled, the thread will terminate. Note: it can be dangerous to sup-
ply an exception handler to treat stack overflow since the client's
stack is used in raising the exception.
exc_uniqpatt() returns an exception pattern that is not any of the pre-
defined patterns (any of the synchronous exceptions or -1 or CATCHALL).
Each call to exc_uniqpatt() results in a different pattern. If
exc_uniqpatt() cannot guarantee uniqueness, -1 is returned instead the
first time this happens. Subsequent calls after this error result in
patterns which may be duplicates.
exc_uniqpatt() returns a unique pattern on success. The first time it
fails, exc_uniqpatt() returns -1.
0 on success.
-1 on failure. When exc_handle() returns because of a matching
call to exc_raise(), it returns the pattern raised by
On success, exc_raise() transfers control to the matching exc_handle()
and does not return. On failure, it returns -1.
0 on success.
-1 on failure.
exc_bound() returns a pointer to a function on success. On failure, it
On success, exc_notify() returns the return value of a function, or
transfers control to a matching exc_handle() and does not return. On
failure, it returns -1.
exc_on_exit() returns 0.
exc_unhandle() will fail if one or more of the following is true:
LE_NONEXIST Attempt to remove a non-existent handler.
Attempt to remove an exit handler.
exc_raise() will fail if one or more of the following is true:
LE_INVALIDARG Attempt to raise an illegal pattern (-1 or 0).
LE_NONEXIST No context found to raise an exception to.
exc_handle() will fail if one or more of the following is true:
LE_INVALIDARG Attempt to handle an illegal pattern (-1 or 0).
exc_uniqpatt() will fail if one or more of the following is true:
LE_REUSE Possible reuse of existing object. agt_create(3L),
The stack may not contain useful information after an exception has
been caught so post-exception debugging can be difficult. The reason
for this is that a given handler may call procedures that trash the
stack before reraising an exception.
The distinction between traps and interrupts can be problematical.
The environment restored on exc_raise() consists of the registers at
the time of the exc_handle(). As a result, modifications to register
variables between the times of exc_handle() and exc_raise() will not be
seen. This problem does not occur in the sun4 implementation.
exc_on_exit() passes a simple type as an argument to the exit routine.
If you need to pass a complex type, such as thread_t, mon_t, or cv_t,
pass a pointer to the object instead.
21 January 1990 EXC_HANDLE(3L)