[an error occurred while processing this directive]
HP OpenVMS Systems Documentation |
HP Pascal for OpenVMS
|
Previous | Contents | Index |
Through the RMS file sharing capability, a file can be accessed by more than one executingprogram at a time or by the same program through more than one file variable. There are two kinds of file sharing: read sharing and write sharing. Read sharing occurs when several programs are reading a file at the same time. Write sharing takes place when at least one program is writing a file and at least one other program is either reading or writing the same file.
The extent to which file sharing can take place is determined by the following factors:
The HISTORY parameter determines how the program will access the file. HISTORY := NEW, HISTORY := OLD, and HISTORY := UNKNOWN determine that the program will read from and write to the file. HISTORY := READONLY determines that the program will only read from the file. If you try to open an existing file with HISTORY := OLD or HISTORY := UNKNOWN, the run-time library retries the OPEN procedure with HISTORY := READONLY if the initial OPEN fails with a privilege violation.
The SHARING parameter determines what other programs are allowed to do with the file. Read sharing can occur when SHARING := READONLY is specified by all programs that access the file. Write sharing is accomplished when all programs specify SHARING := READWRITE. To prevent sharing, specify SHARING:= NONE with the first program to access the file.
Programs that specify SHARING := READONLY or SHARING := READWRITE can access a file simultaneously; however, file sharing can fail under certain circumstances. For example, a program without either of these parameters will fail when it attempts to open a file currently being accessed by some other program. Or, a program that specifies SHARING := READONLY or SHARING := READWRITE can fail to open a file because a second program with a different specification is currently accessing that file.
When two or more programs are write sharing a file, each program should include a condition handler. This error-processing mechanism prevents program failure due to a record-locking error.
The RMS record locking facility, along with the logic of the program, prevents two processes from accessing the same component simultaneously. It ensures that a program can add, delete, or update a component without having to do a synchronization check to determine whether that component is currently being accessed by another process.
When a program opens a relative or indexed file and specifies SHARING := READWRITE, RMS locks each component as it is accessed. When a component is locked, any program that attempts to access it fails and a record-locked error results. A subsequent I/O operation on the file variable unlocks the previously accessed component. Thus, at most one component is locked for each file variable.
If you use the READ procedure, HP Pascal will implicitly unlock the component by executing the UNLOCK procedure during the execution of the READ procedure.
An HP Pascal program can explicitly unlock a component by executing the UNLOCK procedure. To minimize the time during which a component is locked against access by other programs, the UNLOCK procedure should be used in programs that retrieve components from a shared file but that do not attempt to update them. HP Pascal requires that a component be locked before a DELETE or an UPDATE procedure can be executed.
This chapter discusses the following topics:
An exception condition is an event, usually an error, that occurs during program execution and is detected by system hardware or software or the logic in a user application program. A condition handler is a routine that is used to resolve exception conditions.
By default, the Condition Handling Facility (CHF) provides condition handling sufficient for most HP Pascal programs. The CHF also processes user-written condition handlers.
The use of condition handlers requires considerable programming experience. You should understand the discussions of condition handling in the following volumes before attempting to write your own condition handler:
The following terms are used in the discussion of condition handling:
When the OpenVMS system creates a user process, a system-defined condition handler is established in the absence of any user-written condition handler. The system-defined handler processes errors that occur during execution of the user image. Thus, by default, a run-time error causes the system-defined condition handler to print error messages and to terminate or continue execution of the image, depending on the severity of the error.
When a condition is signaled, the system searches for condition handlers to process the condition. The system conducts the search for condition handlers by proceeding down the stack, frame by frame, until a condition handler is found that does not resignal. The default handler calls the system's message output routine to send the appropriate message to the user. Messages are sent to the SYS$OUTPUT and SYS$ERROR files. If the condition is not a severe error, program execution continues. If the condition is a severe error, the default handler forces program termination, and the condition value becomes the program exit status.
You can create and establish your own condition handlers according to
the needs of your application. For example, a condition handler could
create and display messages that describe specific conditions
encountered during the execution of your program, instead of relying on
system error messages.
8.2.1 Condition Signals
A condition signal consists of a call to either LIB$SIGNAL or LIB$STOP, the two entry points to the signaling facility. These entry points can be inherited from SYS$LIBRARY:PASCAL$LIB_ROUTINES.PEN.
If a condition occurs in a routine that is not prepared to handle it, a
signal is issued to notify other active routines. If the current
routine can continue after the signal is propagated, you can call
LIB$SIGNAL. A higher-level routine can then determine whether program
execution should continue. If the nature of the condition does not
allow the current routine to continue, you can call LIB$STOP.
8.2.2 Handler Responses
A condition handler responds to an exception condition by taking action in three major areas:
The handler first determines whether the condition can be corrected. If so, it takes the appropriate action and execution continues. If the handler cannot correct the condition, the condition may be resignaled; that is, the handler requests that another condition handler be sought to process the condition.
A handler's condition reporting can involve one or more of the following actions:
A handler can control execution in several ways:
The following sections describe how to write and establish condition
handlers and provide some simple examples.
8.3.1 Establishing and Removing Handlers
To use a condition handler, you must first declare the handler as a routine in the declaration section of your program; then, within the executable section, you must call the predeclared procedure ESTABLISH. The ESTABLISH procedure sets up an HP Pascal language-specific condition handler that in turn allows your handler to be called. User-written condition handlers set up by ESTABLISH must have the ASYNCHRONOUS attribute and two integer array formal parameters. Such routines can access only local, read-only, and volatile variables, and local, predeclared, and asynchronous routines.
Because condition handlers are asynchronous, any attempt to access a nonread-only or nonvolatile variable declared in an enclosing block will result in a warning message. The predeclared file variables INPUT and OUTPUT are such nonvolatile variables; therefore, simultaneous access to these files from both an ordinary program and from an asynchronous condition handler's activation may have undefined results. The following steps outline the recommended method for performing I/O operations from a condition handler:
External routines (including system services) that are called by a condition handler require the ASYNCHRONOUS attribute in their declaration.
You should set up a user-written condition handler with the predeclared procedure ESTABLISH rather than with the run-time library routine LIB$ESTABLISH. ESTABLISH follows the HP Pascal procedure-calling rules and is able to handle HP Pascal condition handlers more efficiently than LIB$ESTABLISH. A condition handler set up by LIB$ESTABLISH might interfere with the default error handling of the HP Pascal run-time system, and cause unpredictable results.
The following example shows how to establish a condition handler using the HP Pascal procedure ESTABLISH:
[EXTERNAL,ASYNCHRONOUS] FUNCTION Handler (VAR Sigargs : Sigarr; VAR Mechargs : Mecharr) : INTEGER; EXTERN; . . . ESTABLISH (Handler); |
To establish the handler, call the ESTABLISH procedure. To remove an established handler, call the predeclared procedure REVERT, as follows:
REVERT; |
As a result of this call, the condition handler established in the
current stack frame is removed. When control passes from a routine, any
condition handler established during the routine's activation is
automatically removed.
8.3.2 Declaring Parameters for Condition Handlers
A condition handler is an integer-valued function that is called when a condition is signaled. Two formal VAR parameters must be declared for a condition handler:
For example, a condition handler can be defined as follows:
TYPE Sigarr = ARRAY[0..9] OF INTEGER; Mecharr = ARRAY[0..(SIZE(CHF2$TYPE)-4) DIV 4] OF INTEGER; [EXTERNAL,ASYNCHRONOUS] FUNCTION Handler (VAR Sigargs : Sigarr; VAR Mechargs : Mecharr) : INTEGER; EXTERN; . . . ESTABLISH (Handler); . . . |
The signal procedure passes the following values to the array Sigargs:
Value | Description |
---|---|
Sigargs[0] | The number of parameters being passed in this array (parameter count). |
Sigargs[1] | The primary condition being signaled (condition value). See Section 8.3.4 for a discussion of condition values. |
Sigargs[2 to n] | The optional parameters supplied in the call to LIB$SIGNAL or LIB$STOP; note that the index range of Sigargs should include as many entries as are needed to refer to the optional parameters. |
The routine that established the condition handler passes the following values, which contain information about the establisher's routine activation, to the array Mechargs:
OpenVMS I64 Value |
OpenVMS Alpha Value |
OpenVMS VAX Value |
Description |
---|---|---|---|
Mechargs[0] | Mechargs[0] | Mechargs[0] | The number of parameters being passed in this array. |
Not available | Mechargs[2] | Mechargs[1] | The address of the stack frame that established the handler. |
Mechargs[2] | Not available | Not available | The previous stack pointer for the frame that established the handler. |
Mechargs[4] | Mechargs[4] | Mechargs[2] | The number of calls that have been made (that is, the stack frame depth) from the routine activation up to the point at which the condition was signaled. |
Mechargs[11] | Mechargs[11] | Mechargs[3] | The value of register R0 (R8 on OpenVMS I64) at the time of the signal. |
Mechargs[13] | Mechargs[13] | Mechargs[4] | The value of register R1 (R9 on OpenVMS I64) at the time of the signal. |
Condition handlers are functions that return values to control subsequent execution. These values and their effects are listed as follows:
In addition, a condition handler can request a stack unwind by calling the $UNWIND system service routine. You can inherit $UNWIND from SYS$LIBRARY:STARLET.PEN.
When $UNWIND is called, the function return value of the condition handler is ignored. The handler modifies the saved registers R0 and R1 in the mechanism parameters to specify the called function's return value.
A stack unwind is usually made to one of two places:
Status := $UNWIND (Mechargs[2],0); { OpenVMS VAX } Status := $UNWIND (Mechargs[4],0); { OpenVMS I64/OpenVMS Alpha } |
Status := $UNWIND (Mechargs[2]+1,0); { OpenVMS VAX } Status := $UNWIND (Mechargs[4]+1,0); { OpenVMS I64/OpenVMS Alpha } |
The OpenVMS system uses condition values to indicate that a
called routine has either executed successfully or failed, and to
report exception conditions. Condition values are usually symbolic
names that represent
32-bit packed records, consisting of fields (usually interpreted as
integers) that indicate which system component generated the value, the
reason the value was generated, and the severity of the condition.
A warning severity code (0) indicates that although output was produced, the results may be unpredictable. An error severity code (2) indicates that output was produced even though an error was detected. Execution can continue, but the results may not be correct. A severe error code (4) indicates that the error was of such severity that no output was produced.
A condition handler can alter the severity code of a condition value to allow execution to continue or to force an exit, depending on the circumstances.
Occasionally a condition handler may require a particular condition to be identified by an exact match; that is, each bit of the condition value bits (0..31) must match the specified condition. For example, you may want to process a floating overflow condition only if the severity code is still 4 (that is, if no previous condition handler has changed the severity code) and the control bits have not been modified. A typical condition handler response is to change the severity code and resignal.
In most cases, however, you want some response to a condition,
regardless of the value of the severity code or control bits. To ignore
the severity and control fields of a condition value, declare and call
the LIB$MATCH_COND function.
8.3.5 Using Condition Handlers that Return SS$_CONTINUE
HP Pascal condition handlers can do one of the following after appropriately responding to the error:
When an exception occurs, the system calls a handler in the Pascal Run-Time Library that is established by the generated code. This handler in the RTL in turn calls the user condition handler that was established with the ESTABLISH built-in routine.
The RTL handler contains a check to prevent a user handler from returning SS$_CONTINUE for a certain class of Pascal Run-Time Errors that could cause an infinite loop if execution was to continue at the point of the error.
There are two situations in which this check may cause unexpected behavior:
Previous | Next | Contents | Index |