by Conrad Weisert
May 1, 2013
© 2013 Information Disciplines, Inc.
This article may be circulated freely as long as the copyright notice is included.
I was just reading an extended discussion on Linked-In about error-severity levels in a program, and I was struck with the sense of rediscovery of techniques we were using decades ago. I can't think of a textbook that addresses this issue thoroughly, so let me try to start. First let's look at a little historical background:
The SHARE Operating System (SOS) introduced the notion of severity levels. A batch control statement could specify:
|GOIF||Execute only if no errors or warnings have occurred.|
|GO||Execute if no serious errors have occurred.|
|GOGOGO1||Execute no matter what.|
Not all SOS programs observed those conventions and not all 709-7090 installations used SOS, but this convention inspired the more general facility of later systems.
SOS also established the notion of intercepting abnormal events under program control, which led to PL/I's condition handling, which in turn inspired exception processing in today's C-family of programming languages.
OS/360 systematized the notion of condition codes applying to multiple-step batch jobs. Conventions for numerical severity levels were observed by all system processors and by most user programs. Each job-step would set a return code which later steps could test in the Job Control Language (JCL):
|00||No error occurred.|
|04||Warning level (trivial) condition has occurred; continue processing.|
|08||Serious error has occurred; reject transaction.|
|12||Fatal error has occurred; suppress subsequent steps in this job|
|16||Catastrophic error has occurred: terminate processing this job immediately!|
Both the codes and those actions, of course, were only conventional. You could set up a job to do anything you wanted for any return-code values, as long as a program didn't ABEND.2
Some applications extended the OS/360 conventions, especially in the case of transaction processing programs. Our own company and several of our clients adopted the following conventions and provided a standard subroutine for issuing error-diagnostic messages, first in PL/I, later in COBOL, and eventually, with necessary changes, in C++ and Java:
1. Upon encountering an error, the program shall
2. Upon termination of the program, a companion exit routine would set the OS return code to the highest value encountered during the run.
3. A limit, which the program could override, defined a maximum number of errors allowed during the run. When that number was exceeded, the program would terminate. This feature was useful for preventing an out-of-control program from generating hundreds of pages of meaningless output (for example if one accidentally fed a source program to a program expecting a file of transactions).
There were other features, but you get the idea. Programmers liked using the routine, and it was found (and still is) in almost every program developed in those organizations.4
Further obvious refinements were needed to support multi-threaded programs. When should a subtask be allowed to terminate the main task and how?
Let us know if you've developed or if you know of any better way of handling program-discovered errors, diagnostic messages, and severity levels. What related standards, if any, would you support?
firstname.lastname@example.org let us know which language and environment you need it for.
Return to table of contents
Return to technical articles
Last modified May 1, 2013