|
OpenVMS Programming Concepts Manual
Only the condition-value argument must be specified;
other arguments are optional. The condition-value
argument is an OpenVMS 32-bit condition value. The
condition-value argument is an unsigned longword that
contains this condition value.
The number-of-arguments argument, if specified,
contains the number of FAO arguments that are associated with
condition-value. The optional
number-of-arguments argument is a signed longword
integer that contains this number. If omitted or specified as zero, no
FAO arguments follow.
The FAO-argument argument is an optional FAO
(formatted ASCII output) argument that is associated with the specified
condition value.
The condition-value argument indicates the condition
that is being signaled. However, LIB$STOP always sets the severity of
condition-value to SEVERE before proceeding with the
stack-scanning operation.
The FAO arguments describe the details of the exception condition.
These are the same arguments that are passed to the OpenVMS Condition
Handling facility as part of the signal argument vector. The system
default condition handlers pass them to SYS$PUTMSG, which uses them to
issue a system message.
Unlike most routines, LIB$SIGNAL and LIB$STOP preserve R0 and R1 as
well as the other registers. Therefore, a call to LIB$SIGNAL allows the
debugger to display the entire state of the process at the time of the
exception condition. This is useful for debugging checks and gathering
statistics.
The behavior of LIB$SIGNAL is the same as that of the exception
dispatcher that performs the stack scan after hardware detects an
exception condition. That is, the system scans the stack in the same
way, and the same arguments are passed to each condition handler. This
allows a user to write a single condition handler to detect both
hardware and software conditions.
For more information about the RTL routines LIB$SIGNAL and LIB$STOP,
see OpenVMS RTL Library (LIB$) Manual.
9.8.2 Signal Argument Vector
Signaling a condition value causes both VAX and Alpha systems to pass
control to a special subprogram called a condition handler. The
operating system invokes a default condition handler unless you have
established your own. The default condition handler displays the
associated error message and continues or, if the error is a severe
error, terminates program execution.
The signal argument vector contains information describing the nature
of the hardware or software condition. Figure 9-6 illustrates the
open-ended structure of the signal argument vector, which can be from 3
to 257 longwords in length.
The format of the signal argument array and the data it returns is the
same on VAX systems and Alpha systems, with the exception of the
processor status (PS) returned on Alpha systems and the processor
status longword (PSL) returned on VAX systems. On Alpha systems, it is
the low-order 32 bits of the PS.
On Alpha systems, CHF$IS_SIG_ARGS and CHF$IS_SIG_NAME are aliases for
CHF$L_SIG_ARGS and CHF$L_SIG_NAME, as shown in Figure 9-6, and the
PSL field for VAX systems is the processor status (PS) field for Alpha
systems.
Figure 9-6 Format of the Signal Argument Vector
Fields of the Signal Argument Vector
SIGARGS(1)
An unsigned integer (n) designating the number of longwords
that follow in the vector, not counting the first, including PC and
PSL. (On Alpha systems, the value used for the PSL is the low-order
half of the Alpha processor status [PS] register.) For example, the
first entry of a 4-longword vector would contain a 3.
SIGARGS(2)
On both VAX systems and Alpha systems, this argument is a 32-bit value
that uniquely identifies a hardware or software exception condition.
The format of the condition code, which is the same for both VAX
systems and Alpha systems, is shown and described in Figure 9-3.
However, Alpha systems do not support every condition returned on VAX
systems, and Alpha systems define several new conditions that cannot be
returned on VAX systems. Table 9-2 lists VAX system condition codes
that cannot be returned on Alpha systems.
If more than one message is associated with the error, this is the
condition value of the first message. Handlers should always check
whether the condition is the one that they expect by examining the
STS$V_COND_ID field of the condition value (bits <27:3>). Bits
<2:0> are the severity field. Bits <31:28> are control
bits; they may have been changed by an intervening handler and so
should not be included in the comparison. You can use the RTL routine
LIB$MATCH_COND to match the correct fields. If the condition is not
expected, the handler should resignal by returning false (bit <0>
= 0). The possible exception conditions and their symbolic definitions
are listed in Table 9-1.
SIGARGS(3 to n --1)
Optional arguments that provide additional information about the
condition. These arguments consist of one or more message sequences.
The format of the message description varies depending on the type of
message being signaled. For more information, see the SYS$PUTMSG
description in the OpenVMS System Services Reference Manual. The format of a message sequence is
described in Section 9.11.
SIGARGS(n)
The program counter (PC) of the next instruction to be executed if any
handler (including the system-supplied handlers) returns with the
status SS$_CONTINUE. For hardware faults, the PC is that of the
instruction that caused the fault. For hardware traps, the PC is that
of the instruction following the one that caused the trap. The error
generated by LIB$SIGNAL is a trap. For conditions signaled by calling
LIB$SIGNAL or LIB$STOP, the PC is the location following the CALLS or
CALLG instruction. See the VAX Architecture Reference Manual or Alpha Architecture Reference Manual for a
detailed description of faults and traps.
SIGARGS(n+1)
On VAX systems the processor status longword (PSL), or on Alpha systems
the processor status (PS) register, of the program at the time that the
condition was signaled.
For information about the PSL on VAX systems, and the PS on Alpha
systems, see the VAX Architecture Reference Manual and the Alpha Architecture Reference Manual.
Note
LIB$SIGNAL and LIB$STOP copy the variable-length argument list passed
by the caller. Then, before calling a condition handler, they append
the PC and PSL (or on Alpha systems the processor status (PS) register)
entries to the end of the list.
|
The formats for some conditions signaled by the operating system and
the run-time library are shown in Figure 9-7 and Figure 9-8.
These formats are the same on VAX systems and Alpha systems, except for
the PSL, or on Alpha systems, the PS register.
Figure 9-7 Signal Argument Vector for the Reserved Operand
Error Conditions
Figure 9-8 Signal Argument Vector for RTL Mathematics Routine
Errors
The caller's PC is the PC following the calling program's JSB or CALL
to the mathematics routine that detected the error. The PC is that
following the call to LIB$SIGNAL.
9.8.3 VAX Mechanism Argument Vector (VAX Only)
On VAX systems, the mechanism argument vector is a 5-longword vector
that contains all of the information describing the state of the
process at the time of the hardware or software signaled condition.
Figure 9-9 illustrates a mechanism argument vector for VAX systems.
Figure 9-9 Format of a VAX Mechanism Argument Vector
Fields of the VAX Mechanism Argument Vector
MCHARGS(1)
An unsigned integer indicating the number of longwords that follow, not
counting the first, in the vector. Currently, this number is always 4.
MCHARGS(2)
The address of the stack frame of the routine that established the
handler being called. You can use this address as a base from which to
reference the local stack-allocated storage of the establisher, as long
as the restrictions on the handler's use of storage are observed. For
example, if the call stack is as shown in Figure 9-4, this argument
points to the call frame for procedure A.
You can use this value to display local variables in the procedure that
established the condition handler if the variables are at known offsets
from the frame pointer (FP) of the procedure.
MCHARGS(3)
The stack depth, which is the number of stack frames between the
establisher of the condition handler and the frame in which the
condition was signaled. To ensure that calls to LIB$SIGNAL and LIB$STOP
appear as similar as possible to hardware exception conditions, the
call to LIB$SIGNAL or LIB$STOP is not included in the depth.
If the routine that contained the hardware exception condition or that
called LIB$SIGNAL or LIB$STOP also handled the exception condition,
then the depth is zero; if the exception condition occurred in a called
routine and its caller handled the exception condition, then the depth
is 1. If a system service signals an exception condition, a handler
established by the immediate caller is also entered with a depth of 1.
The following table shows the stack depths for the establishers of
condition handlers:
Depth |
Meaning |
--3
|
Condition handler was established in the last-chance exception vector.
|
--2
|
Condition handler was established in the primary exception vector.
|
--1
|
Condition handler was established in the secondary exception vector.
|
0
|
Condition handler was established by the frame that was active when the
exception occurred.
|
1
|
Condition handler was established by the caller of the frame that was
active when the exception occurred.
|
2
|
Condition handler was established by the caller of the caller of the
frame that was active when the exception occurred.
|
.
|
|
.
|
|
.
|
|
For example, if the call stack is as shown in Figure 9-4, the depth
argument passed to handler A would have a value of 2.
The condition handler can use this argument to determine whether to
handle the condition. For example, the handler might not want to handle
the condition if the exception that caused the condition did not occur
in the establisher frame.
MCHARGS(4) and MCHARGS(5)
Copies of the contents of registers R0 and R1 at the time of the
exception condition or the call to LIB$SIGNAL or LIB$STOP. When
execution continues or a stack unwind occurs, these values are restored
to R0 and R1. Thus, a handler can modify these values to change the
function value returned to a caller.
9.8.4 Alpha Mechanism Argument Vector (Alpha Only)
On Alpha systems, the mechanism array returns much the same data as it
does on VAX systems, though its format is changed. The mechanism array
returned on Alpha systems preserves the contents of a larger set of
integer scratch registers as well as the Alpha floating-point scratch
registers. In addition, because Alpha registers are 64 bits long, the
mechanism array is constructed of quadwords (64 bits), not longwords
(32 bits) as it is on VAX systems. Figure 9-10 shows the format of
the mechanism array on Alpha systems.
Figure 9-10 Mechanism Array on Alpha Systems
Table 9-11 describes the arguments in the mechanism array.
Table 9-11 Fields in the Alpha Mechanism Array
Argument |
Description |
CHF$IS_MCH_ARGS
|
Represents the number of quadwords in the mechanism array, not counting
the argument count quadword. (The value contained in this argument is
always 43.)
|
CHF$IS_MCH_FLAGS
|
Flag bits <63:0> for related argument mechanism information
defined as follows for CHF$V_FPREGS:
Bit <0>: When set, the process has already performed a
floating-point operation and the floating-point registers stored in
this structure are valid.
If this bit is clear, the process has not yet performed any
floating-point operations, and the values in the floating-point
register slots in this structure are unpredictable.
|
CHF$PH_MCH_FRAME
|
The frame pointer (FP) in the procedure context of the establisher.
|
CHF$IS_MCH_DEPTH
|
Positive count of the number of procedure activation stack frames
between the frame in which the exception occurred and the frame depth
that established the handler being called.
|
CHF$PS_MCH_DADDR
|
Address of the handler data quadword if the exception handler data
field is present (as indicated by PDSC.FLAGS.HANDLER_DATA_VALID);
otherwise, contains zero.
|
CHF$PH_MCH_ESF_ADDR
|
Address of the exception stack frame (see the Alpha Architecture Reference Manual).
|
CHF$PH_MCH_SIG_ADDR
|
Address of the signal array. The signal array is a 32-bit (longword)
array.
|
CHF$IH_MCH_SAVR
nn
|
A copy of the saved integer registers at the time of the exception. The
following registers are saved: R0, R1, and R16--R28. Registers R2--R15
are implicitly saved in the call chain.
|
CHF$FM_MCH_SAVF
nn
|
A copy of the saved floating-point registers at the time of the
exception or may have unpredictable data as described in
CHF$IS_MCH_FLAGS. If the floating-point register fields are valid, the
following registers are saved: F0, F1, and F10--F30. Registers F2--F9
are implicitly saved in the call chain.
|
For more information and recommendations about using the mechanism
argument vector on Alpha systems, see Migrating to an OpenVMS AXP System: Recompiling and Relinking Applications. Note that this
manual has been archived but is available on the OpenVMS Documentation
CD-ROM.
9.8.5 Multiple Active Signals
A signal is said to be active until the routine that signaled regains
control or until the stack is unwound or the image exits. A second
signal can occur while a condition handler or a routine it has called
is executing. This situation is called multiple active
signals or multiple exception conditions.
When this situation occurs, the stack scan is not performed in the
usual way. Instead, the frames that were searched while processing all
of the previous exception conditions are skipped when the current
exception condition is processed. This is done in order to avoid
recursively reentering a routine that is not reentrant. For example,
Fortran code typically is not recursively reentrant. If a Fortran
handler were called while another activation of that handler was still
going, the results would be unpredictable.
A second exception may occur while a condition handler or a procedure
that it has called is still executing. In this case, when the exception
dispatcher searches for a condition handler, it skips the frames that
were searched to locate the first handler.
The search for a second handler terminates in the same manner as the
initial search, as described in Section 9.6.
If the SYS$UNWIND system service is issued by the second active
condition handler, the depth of the unwind is determined according to
the same rules followed in the exception dispatcher's search of the
stack: all frames that were searched for the first condition handler
are skipped.
Primary and secondary vectored handlers, on the other hand, are always
entered when an exception occurs.
If an exception occurs during the execution of a handler that was
established in the primary or secondary exception vector, that handler
must handle the additional condition. Failure to do so correctly might
result in a recursive exception loop in which the vectored handler is
repeatedly called until the user stack is exhausted.
The modified search routine is best illustrated with an example. Assume
the following calling sequence:
- Routine A calls routine B, which calls routine C.
- Routine C signals an exception condition (signal S), and the
handler for routine C (CH) resignals.
- Control passes to BH, the handler for routine B. The call frame for
handler BH is located on top of the signal and mechanism arrays for
signal S. The saved frame pointer in the call frame for BH points to
the frame for routine C.
- BH calls routine X; routine X calls routine Y.
- Routine Y signals a second exception condition (signal T).
Figure 9-11 illustrates the stack contents after the second exception
condition is signaled.
Figure 9-11 Stack After Second Exception Condition Is
Signaled
Normally, the OpenVMS Condition Handling facility (CHF) searches
all currently active frames for condition handlers, including B and C.
If this happens, however, BH is called again. At this point, you skip
the condition handlers that have already been called. Thus, the search
for condition handlers should proceed in the following order:
YH
XH
BHH (the handler for routine B's handler)
AH
- The search now continues in its usual fashion. The CHF examines the
primary and secondary exception vectors, then frames Y, X, and BH.
Thus, handlers YH, XH, and BHH are called. Assume that these handlers
resignal.
- The CHF now skips the frames that have already been searched and
resumes the search for condition handlers in routine A's frame. The
depths that are passed to handlers as a result of this modified search
are 0 for YH, 1 for XH, 2 for BHH, and 3 for AH.
Because of the possibility of multiple active signals, you should be
careful if you use an exception vector to establish a condition
handler. Vectored handlers are called, not skipped, each time an
exception occurs.
9.9 Types of Condition Handlers
On VAX systems, when a routine is activated, the first longword in its
stack frame is set to 0. This longword is reserved to contain an
address pointing to another routine called the condition handler. If an
exception condition is signaled during the execution of the routine,
the OpenVMS Condition Handling Facility uses the address in the first
longword of the frame to call the associated condition handler.
On Alpha systems, each procedure, other than a null frame procedure,
can have a condition handler potentially associated with it, identified
by the HANDLER_VALID, STACK_HANDLER, or REG_HANDLER field of the
associated procedure descriptor. You establish a handler by including
the procedure value of the handler procedure in that field.
The arguments passed to the condition-handling routine are the signal
and mechanism argument vectors, described in Section 9.8.2,
Section 9.8.3, and Section 9.8.4.
Various types of condition handlers can be called for a given routine:
- User-supplied condition handlers
You can write your own
condition handler and set up its address in the stack frame of your
routine using the run-time library routine LIB$ESTABLISH or the
mechanism supplied by your language. On Alpha systems,
LIB$ESTABLISH is not supported, though high-level languages may support
it for compatibility.
- Language-supplied condition handlers
Many high-level languages provide a means for setting up handlers
that are global to a single routine. If your language provides a
condition-handling mechanism, you should always use it. If you also try
to establish a condition handler using LIB$ESTABLISH, the two methods
of handling exception conditions conflict, and the results are
unpredictable.
- System default condition handlers
The operating system provides
a set of default condition handlers. These take over if there are no
other condition handler addresses on the stack, or if all the previous
condition handlers have passed on (resignaled) the indication of the
exception condition.
9.9.1 Default Condition Handlers
The operating system establishes the following default condition
handlers each time a new image is started. The default handlers are
shown in the order they are encountered when the operating system
processes a signal. These three handlers are the only handlers that
output error messages.
- Traceback handler
The traceback handler is established on the
stack after the catchall handler. This enables the traceback handler to
get control first. This handler performs three functions in the
following order:
- Outputs an error message using the Put Message (SYS$PUTMSG) system
service. SYS$PUTMSG formats the message using the Formatted ASCII
Output (SYS$FAO) system service and sends the message to the devices
identified by the logical names SYS$ERROR and SYS$OUTPUT (if it differs
from SYS$ERROR). That is, it displays the message associated with the
signaled condition code, the traceback message, the program unit name
and line number of the statement that signaled the condition code, and
the relative and absolute program counter values. (On a warning or
error, the number of the next statement to be executed is displayed.)
- Issues a symbolic traceback, which shows the state of the routine
stack at the time of the exception condition. That is, it displays the
names of the program units in the calling hierarchy and the line
numbers of the invocation statements.
- Decides whether to continue executing the image or to force an exit
based on the severity field of the condition value:
Severity |
Error Type |
Action |
1
|
Success
|
Continue
|
3
|
Information
|
Continue
|
0
|
Warning
|
Continue
|
2
|
Error
|
Continue
|
4
|
Severe
|
Exit
|
The traceback handler is in effect if you link your program with
the /TRACEBACK qualifier of the LINK command (the default). Once you
have completed program development, you generally link your program
with the /NOTRACEBACK qualifier and use the catchall handler.
- Catchall handler
The operating system establishes the catchall
handler in the first stack frame and thus calls it last. This handler
performs the same functions as the traceback handler except for the
stack traceback. That is, it issues an error message and decides
whether to continue execution. The catchall is called only if you link
with the /NOTRACEBACK qualifier. It displays the message associated
with the condition code and then continues program execution or, if the
error is severe, terminates execution.
- Last-chance handler
The operating system establishes the
last-chance handler with a system exception vector. In most cases, this
vector contains the address of the catchall handler, so that these two
handlers are actually the same. The last-chance handler is called only
if the stack is invalid or all the handlers on the stack have
resignaled. If the debugger is present, the debugger's own last-chance
handler replaces the system last-chance handler.
Displays the message associated with the condition code and then
continues program execution or, if the error is severe, terminates
execution. The catchall handler is not invoked if the traceback handler
is enabled.
In the following example, if the condition code INCOME_LINELOST is
signaled at line 496 of GET_STATS, regardless of which default handler
is in effect, the following message is displayed:
%INCOME-W-LINELOST, Statistics on last line lost due to CTRL/Z
|
If the traceback handler is in effect, the following text is also
displayed:
%TRACE-W-TRACEBACK, symbolic stack dump follows
module name routine name line rel PC abs PC
GET_STATS GET_STATS 497 00000306 00008DA2
INCOME INCOME 148 0000015A 0000875A
0000A5BC 0000A5BC
00009BDB 00009BDB
0000A599 0000A599
|
Because INCOME_LINELOST is a warning, the line number of the next
statement to be executed (497), rather than the line number of the
statement that signaled the condition code, is displayed. Line 148 of
the program unit INCOME invoked GET_STATS.
|