HP OpenVMS Systems Documentation

Content starts here

HP Pascal for OpenVMS
User Manual

Previous Contents Index

7.3 File Sharing

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:

  • Device type
    Sharing is possible only on disk files, since other files must be accessed sequentially.
  • File organization
    All three file organizations permit read and write sharing on disk files.
  • Explicit user-supplied information
    Whether or not file sharing actually takes place depends on two items of information that you provide for each program accessing the file. In HP Pascal programs, this information is supplied by the values of the SHARING and HISTORY parameters in the OPEN procedure.

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.

For More Information:

  • On record-locking errors ( Section 7.4)
  • On condition handling (Chapter 8)
  • On the OPEN procedure (HP Pascal for OpenVMS Language Reference Manual)

7.4 Record Locking

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.

For More Information:

  • On the OPEN, UNLOCK, DELETE, and UPDATE procedures (HP Pascal for OpenVMS Language Reference Manual)

Chapter 8
Error Processing and Condition Handling

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:

  • HP OpenVMS Programming Concepts Manual
  • HP OpenVMS System Services Reference Manual
  • HP OpenVMS Calling Standard

8.1 Condition Handling Terms

The following terms are used in the discussion of condition handling:

  • Condition value---An integer value that identifies a specific condition.
  • Stack frame---A standard data structure built on the stack during a routine call, starting from the location addressed by the frame pointer (FP) and proceeding to both higher and lower addresses; it is popped off the stack during the return from a routine.
  • Routine activation---The environment in which a routine executes. This environment includes a unique stack frame on the run-time stack; the stack frame contains the address of a condition handler for the routine activation. A new routine activation is created every time a routine is called and is deleted when control passes from the routine.
  • Establish---The process of placing the address of a condition handler in the stack frame of the current routine activation. A condition handler established for a routine activation is automatically called when a condition occurs. In HP Pascal, condition handlers are established by means of the predeclared procedure ESTABLISH. A routine that establishes a condition handler is known as an establisher.
  • Program exit status---The status of the program at its completion.
  • Signal---The means by which the occurrence of an exception condition is made known. Signals are generated by the operating system in response to I/O events and hardware errors, by the system-supplied library routines, and by user routines. All signals are initiated by a call to the signaling facility, for which there are two entry points:
    • LIB$SIGNAL---Used to signal a condition and, possibly, to continue program execution
    • LIB$STOP---Used to signal a severe error and discontinue program execution, unless a condition handler performs an unwind operation
  • Resignal---The means by which a condition handler indicates that the signaling facility is to continue searching for a condition handler to process a previously signaled error. To resignal, a condition handler returns the value SS$_RESIGNAL.
  • Unwind---The return of control to a particular routine activation, bypassing any intermediate routine activations. For example, if X calls Y, and Y calls Z, and Z detects an error, then a condition handler associated with X or Y can unwind to X, bypassing Y. Control returns to X immediately following the point at which X called Y.

8.2 Overview 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:

  • Condition correction
  • Condition reporting
  • Execution control

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:

  • Maintaining a count of exceptions encountered during program execution
  • Resignaling the same condition to send the appropriate message to the output file
  • Changing the severity field of the condition value and resignaling the condition
  • Signaling a different condition, for example, the production of a message designed for a specific application

A handler can control execution in several ways:

  • By continuing from the signal. If the signal was issued through a call to LIB$STOP, the program exits.
  • By doing a nonlocal GOTO operation (see Section 8.5, Example 5).
  • By unwinding to the establisher at the point of the call that resulted in the exception. The handler can then determine the function value returned by the called routine.
  • By unwinding to the establisher's caller (the routine that called the routine which established the handler). The handler can then determine the function value returned by the called routine.

8.3 Writing Condition Handlers

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:

  1. Declare a file with the VOLATILE attribute at program level.
  2. Open this file to refer to SYS$INPUT, SYS$OUTPUT, or another appropriate file.
  3. Use this file in the 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:

   (VAR Sigargs  : Sigarr;
    VAR Mechargs : Mecharr) : INTEGER;
ESTABLISH (Handler);

To establish the handler, call the ESTABLISH procedure. To remove an established handler, call the predeclared procedure REVERT, as follows:


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:

  • An integer array to refer to the parameter list from the call to the signal routine (the signal array); that is, the list of parameters included in calls to LIB$SIGNAL or LIB$STOP (see Section 8.2.1)
  • An integer array to refer to information concerning the routine activation that established the condition handler (the mechanism array). The size and contents of the mechanism array is different on OpenVMS I64, OpenVMS Alpha, and OpenVMS VAX systems.

For example, a condition handler can be defined as follows:

   Sigarr  = ARRAY[0..9] OF INTEGER;
   Mecharr = ARRAY[0..(SIZE(CHF2$TYPE)-4) DIV 4] OF INTEGER;

   (VAR Sigargs : Sigarr;
    VAR Mechargs : Mecharr)   : INTEGER;
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
OpenVMS Alpha
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.
For a complete description of the mechanism array, see the HP OpenVMS Calling Standard.

8.3.3 Handler Function Return Values

Condition handlers are functions that return values to control subsequent execution. These values and their effects are listed as follows:

Value Effect
SS$_CONTINUE Continues execution from the signal. If the signal was issued by a call to LIB$STOP, the program does not continue, but exits.
SS$_RESIGNAL Resignals to continue the search for a condition handler to process the condition.

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:

  • The point in the establisher at which the call was made that resulted in the exception. Specify the following:

    Status := $UNWIND (Mechargs[2],0); { OpenVMS VAX }
    Status := $UNWIND (Mechargs[4],0); { OpenVMS I64/OpenVMS Alpha }
  • The routine that called the establisher. Specify the following:

    Status := $UNWIND (Mechargs[2]+1,0); { OpenVMS VAX }
    Status := $UNWIND (Mechargs[4]+1,0); { OpenVMS I64/OpenVMS Alpha }

8.3.4 Condition Values and Symbols

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:

  • Use a nonlocal GOTO to transfer control to a label in an enclosing block
  • Return SS$_CONTINUE if the handler is conditioned to dismiss the error then signal to continue processing
  • Return SS$_RESIGNAL if the handler is conditioned to continue searching for additional handlers to call
  • Call the $UNWIND system service to establish a new point to resume execution when the handler returns to the system

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:

  • The user handler called $UNWIND and then returned with SS$_CONTINUE. Because the $UNWIND service was called, execution will not resume at the point of the error even if SS$_CONTINUE is returned to the system. However, the RTL handler is not aware that $UNWIND has been called, and will report that program operation cannot continue for this type of error. The solution is to return SS$_RESIGNAL instead of SS$_CONTINUE after calling $UNWIND in the user handler.
    However, this solution is not possible if you establish the LIB$SIG_TO_RET routine with the ESTABLISH built-in routine. LIB$SIG_TO_RET is a routine that can be used as a condition handler to convert a signal into a return to the caller of the routine that established LIB$SIG_TO_RET. Because LIB$SIG_TO_RET returns SS$_NORMAL, which in turn is the same value as SS$_CONTINUE, the handler in the Pascal RTL will report that program operation cannot continue for this type of error. The solution for this case is to establish your own handler with the ESTABLISH built-in routine that calls LIB$SIG_TO_RET and then returns SS$_RESIGNAL. You cannot establish LIB$SIG_TO_RET directly as a handler with the ESTABLISH built-in routine.
  • If you are moving code from OpenVMS VAX to OpenVMS I64 or OpenVMS Alpha.
    On OpenVMS VAX systems, only certain run-time errors are not allowed to return SS$_CONTINUE from a handler. These errors are those associated with the SUBSTR and PAD built-in routines, and those associated with checking code for set constructors. On OpenVMS I64 and OpenVMS Alpha systems, many more run-time errors are not allowed to return SS$_CONTINUE from a handler. It is recommended that you do not return SS$_CONTINUE for any Pascal run-time error that is not associated with a file operation.

For More Information:

  • On the format of a condition value (HP OpenVMS Calling Standard)
  • On calling the LIB$MATCH_COND function ( Section 8.5)

Previous Next Contents Index