Low-Level Error Handling
Published By | Date | Version | Knowledge Level | Keywords |
---|---|---|---|---|
Revelation Technologies | 10 OCT 1990 | 2.X | EXPERT | BFS/MFS, FSMSG, STDIOERR, STDIOERR_CTL |
One of the design goals of Advanced Revelation 2.0 was to provide tighter control over low level I/O errors. That goal was realized. This Technical Bulletin provides information about handling low level I/O errors.
The BFS/MFS Protocol
In order to be compatible with 2.0, all BFSs and MFSs must adhere to a new error-reporting protocol. Details of the protocol are provided in Technical Bulletin #43.
One part of the protocol deals with setting STATUS(). All I/O failures set STATUS() to one of the following values, indicating the severity of the failure.
Code | Description |
---|---|
0 | Logical error-the operation failed for logical reasons. For example, a security MFS might fail a write if the user's privelege level was not high enough. |
1 | Physical error - the error may be transient, a retry may safely be executed. For example, a BFS dedicated to file access via phone lines might find a problem with the line. Retrying the operation might succeed. |
2 | Fatal error - the operation should not be retried until the problem has been corrected. This would be the case, for example, when the disk has been corrupted. |
In addition to setting STATUS(), BFSs and MFSs set @FILE.ERROR, which contains detailed information about the error. The layout of @FILE.ERROR is:
Field | Description |
---|---|
1 | The error code. See the equate records in the INCLUDE file for a listing of the codes and their meanings. |
2 | Detail support for the error. For example, a record key or a file name might be given. Whether or not this field is required depends on the error code. See the INCLUDE file for specific errors. |
3 | Additional error text, if needed. |
I/O Errors: FSMSG
Whenever an I/O operation fails, control is passed back to the calling program on the ELSE branch. This is where you typically include error processing. To relieve you of having to deal with all possible errors, the system has a default error handler: FSMSG.
FSMSG allows you to handle errors selectively or not at all. For example, your program might have code like this:
READ REC FROM FILE_IN_FILE ELSE IF @FILE.ERROR<FSCODE$> = FS_REC_DNE$ ELSE FSMSG() END END
In the example above, the program calls FSMSG for all errors other than "Record does not exist", which is simply ignored.
DELETE REC FROM SOURCE_FILE ELSE FSMSG() END
In this example all DELETE failures are passed to FSMSG.
Low-Level Errors: STDIOERR
Low level errors differ from high-level errors in that application programs are not generally expected to have to interpret them. These errors are expected to occur so infrequently that your programs should rarely, if ever, see them.
To deal with low level errors, a standard error handler is provided, STDIOERR.
STDIOERR is called under the following circumstances:
- All logical failures of DELETE and WRITE operations that do not have a branch. Even if the only branch statement provided is THEN, the error handler will not be called.
Note: A special case is allowed for attempts to delete non-existent records. If such an attempt is made, STDIOERR is not called. - All physical and fatal DELETE and WRITE errors.
- All physical or fatal errors on READ or READO statements.
- All physical or fatal errors on READNEXT.
STDIOERR_CTL
The text displayed by STDIOERR and the actions to be performed come from a record in the SYS.HELP file, STDIOERR_CTL. The layout of this record is:
Field | Description |
---|---|
1 | Read error text "Reading" |
2 | Write error text "Writing" |
3 | Delete error text "Deleting" |
4 | Readnext error text "Readnexting" |
5 | Conjuction text "in file" |
6 | Logical error prompt |
7 | Physical error prompt |
8 | Fatal error prompt |
9 | Action keys |
10 | Action codes |
11 | Action commands |
12 | Escape action code |
13 | Escape action command |
Fields 6 - 8 are multivalued. Each field has this layout:
Value | Description |
---|---|
1 | Error level text Ä "Logical error" |
2 | Prompt text Ä "Break to debugger, Continue? (B/C)" |
3 | Action character list Ä "BC" |
Fields 9 - 11 are associated multivalues. Each field is related to the others. The code in value one of field 10 corresponds to the action key in value one of field 9. When the user presses the action key, the corresponding code (and command) is executed.
Fields 12 and 13 define the action to take place when the user presses [Esc].
Three codes are predefined. No command is required if these codes are used.
Code | Description |
---|---|
1 | ABORT ALL |
2 | Break to Debugger |
3 | Do nothing, return control to the program |
If you execute your own program via a CATALYST code and command, information about the error can be found in @ANS. That information is:
Field | Description |
---|---|
1 | Filing system code |
2 | Error level (from STATUS(), see above) |
3 | Record key |
4 | Revelation file name |
By modifying STDIOERR_CTL, you can control the options presented to the user and what happens when as option is selected.
Considerations
If you modify STDIOERR_CTL, there are several issues to keep in mind.
First, remember that STDIOERR is global. It will be called for all low-level errors, not just those for a specific process or file. Your changes must be applicable to all files and all processes.
Second, STDIOERR requires user interaction. Even if a user has no choices, a message requiring input from the user is displayed.
Third, the action keystrokes must be unique. That is, you cannot have the letter "B" mean one thing for logical errors and another for physical errors without writing your own routine. See Figure 1 for an example of how to decide what action to perform.
Finally, note that the processing for [Esc] is the same for all error levels.
Avoiding STDIOERR
It is possible for your programs to prevent calls to STDIOERR. If you elect to take responsibility for all errors, including fatal errors, you can set the system variable @FILE.ERROR.MODE to 1 (true).
If STDIOERR would normally be called and @FILE.ERROR.MODE is true, control is returned to your program and you can deal with the error.
@FILE.ERROR.MODE is reset to false everytime you go down an execution level and whenever a RESET is executed. However, you should exercise caution whenever you set @FILE.ERROR.MODE, to avoid affecting programs that do not deal with low level errors. See Figure 2 for an example of how to use @FILE.ERROR.MODE.
Examples
Figure 1
SUBROUTINE ERR_HANDLER /* A program that allows the same action keystroke to be used for different severity levels. */ ERR_INFO = @ANS ERR_LEVEL = ERR_INFO<2> BEGIN CASE CASE ERR_LEVEL = 0 /* Logical error. */ CASE ERR_LEVEL = 1 /* Physical error. */ CASE ERR_LEVEL = 2 /* Fatal error. */ END CASE RETURN
Figure 2
EQU TRUE$ TO 1 EQU FALSE$ TO 0 (...) DONE = FALSE$ LOOP READNEXT KEY FROM FILE_CUST ELSE DONE = TRUE$ END UNTIL DONE @FILE.ERROR.MODE = TRUE$ READ REC FROM FILE_CUST THEN /* Normal record processing. */ END ELSE /* Error of some sort. */ BEGIN CASE CASE STATUS() = 0 /* Logical error. */ CASE STATUS() = 1 /* Physical error. */ CASE STATUS() = 2 /* Fatal error. */ END CASE END @FILE.ERROR.MODE = FALSE$ REPEAT