Chapter 3 Exceptions and Exception Handling RealTime Systems

















































- Slides: 49

Chapter 3: Exceptions and Exception Handling Real-Time Systems and Programming Languages © Alan Burns and Andy Wellings

Aims n n To illustrate the various model of exception handing To consider the Ada and Java models of exception handling in detail and to show exception handling can be used as a framework for implementing fault-tolerant systems Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 2 - 49

Exceptions and their Representation n n Environmental detection and application error detection A synchronous exception is raised as an immediate result of a process attempting an inappropriate operation An asynchronous exception is raised some time after the operation causing the error; it may be raised in the process which executed the operation or in another process Asynchronous exceptions are often called asynchronous notifications or signals and will be considered later Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 3 - 49

Classes of Exceptions n n Detected by the environment and raised synchronously; e. g. array bounds error or divide by zero Detected by the application and raised synchronously, e. g. the failure of a program-defined assertion check Detected by the environment and raised asynchronously; e. g. an exception raised due to the failure of some health monitoring mechanism Detected by the application and raised asynchronously; e. g. one process may recognise that an error condition has occurred which will result in another process not meeting its deadline or not terminating correctly Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 4 - 49

Synchronous Exceptions n There are two models for their declaration Ø Ø a constant name which needs to be explicitly declared, e. g. Ada an object of a particular type which may or may not need to be explicitly declared; e. g. Java Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 5 - 49

The Domain of an Exception Handler n n n Within a program, there may be several handlers for a particular exception Associated with each handler is a domain which specifies the region of computation during which, if an exception occurs, the handler will be activated The accuracy with which a domain can be specified will determine how precisely the source of the exception can be located Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 6 - 49

Ada n In a block structured language, like Ada, the domain is normally the block. declare subtype Temperature is Integer range 0. . 100; begin -- read temperature sensor and calculate its value exception -- handler for Constraint_Error end; n Procedures, functions, accept statements etc. can also act as domains Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 7 - 49

Java n Not all blocks can have exception handlers. Rather, the domain of an exception handler must be explicitly indicated and the block is considered to be guarded; in Java this is done using a try-block try { // statements which may raise exceptions } catch (Exception. Type e) { // handler for e } Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 8 - 49

Exception propagation n If there is no handler associated with the block or procedure Ø Ø Ø regard it as a programmer error which is reported at compile time but an exception raised in a procedure can only be handled within the context from which the procedure was called eg, an exception raised in a procedure as a result of a failed assertion involving the parameters Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 9 - 49

Alternative Approach n Look for handlers up the chain of invokers; this is called propagating the exception — the Ada and Java approach Ø Ø n n A problem occurs where exceptions have scope; an exception may be propagated outside its scope, thereby making it impossible for a handler to be found Most languages provide a catch all exception handler An unhandled exception causes a sequential program to be aborted If the program contains more than one process and a particular process does not handle an exception it has raised, then usually that process is aborted Ø However, it is not clear whether the exception should be propagated to the parent process Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 10 - 49

Resumption versus termination model n n Should the invoker of the exception continue its execution after the exception has been handled? If the invoker can continue, then it may be possible for the handler to cure the problem that caused the exception to be raised and for the invoker to resume as if nothing has happened Ø n n This is referred to as the resumption or notify model The model where control is not returned to the invoker is called termination or escape Clearly it is possible to have a model in which the handler can decide whether to resume the operation which caused the exception, or to terminate the operation; this is called the hybrid model Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 11 - 49

The Resumption Model Hq Hq resumes Hr Hr raises q P invokes Q P Hr R raises r Hr resumes R Q Q invokes R R Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 12 - 49

The Resumption Model n n n Problem: it is difficult to repair errors raised by the RTS Eg, an arithmetic overflow in the middle of a sequence of complex expressions results in registers containing partial evaluations; calling the handler overwrites these registers Pearl & Mesa support the resumption and termination models Implementing a strict resumption model is difficult, a compromise is to re-execute the block associated with the exception handler; Eiffel provides such a facility. Note that for such a scheme to work, the local variables of the block must not be re-initialised on a retry The advantage of the resumption model comes when the exception has been raised asynchronously and, therefore, has little to do with the current process execution Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 13 - 49

The Termination Model declare subtype Temperature is Integer range 0. . 100; begin. . . begin -- read temperature sensor and calculate its value, -- may result in an exception being raised exception -- handler for Constraint_Error for temperature, -- once handled this block terminates end; -- code here executed when block exits normally -- or when an exception has been raised and handled. exception -- handler for other possible exceptions end; n With procedures, as opposed to blocks, the flow of control can quite dramatically change n Ada and Java support the termination model Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 14 - 49

The Termination Model Procedure P P invokes Q Procedure Q Q invokes R Procedure R Handler sought Procedure terminates Handler for r Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 15 - 49 Exception r raised

Exception Handling in Ada n n Ada supports: explicit exception declaration, the termination model, propagation of unhandled exceptions, and a limited form of exception parameters. Exception declared: either by language keyword: stuck_valve : exception; n n or by the predefined package Ada. Exceptions which defines a private type called Exception_Id Every exception declared by keyword has an associated Exception_Id which can be obtained using the predefined attribute Identity Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 16 - 49

package Ada. Exceptions is type Exception_Id is private; Null_Id : constant Exception_Id; function Exception_Name(Id : Exception_Id) return String; type Exception_Occurrence is limited private; Null_Occurrence : constant Exception_Occurrence; procedure Raise_Exception(E : in Exception_Id; Message : in String : = ""); function Exception_Message(X : Exception_Occurrence) return String; procedure Reraise_Occurrence(X : in Exception_Occurrence); function Exception_Identity(X : Exception_Occurrence) return Exception_Id; function Exception_Name(X : Exception_Occurrence) return String; function Exception_Information(X : Exception_Occurrence) return String; . . private. . . -- not specified by the language end Ada. Exceptions;

Raising an Exceptions may be raised explicitly begin. . . -- statements which request a device to -- perform some I/O if IO_Device_In_Error then raise IO_Error; end if; -- no else, as no return from raise. . . end; n If IO_Error was of type Exception_Id, it would have been necessary to use Ada. Exceptions. Raise_Exception; this would have allowed a textual string to be passed as a parameter to the exception. n Each individual raising of an exception is called an exception occurrence n The handler can find the value of the Exception_Occurrence and used it to determine more information about the cause of the exception Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 18 - 49

Exception Handling n n Optional exception handlers can be declared at the end of the block (or subprogram, accept statement or task) Each handler is a sequence of statements declare Sensor_High, Sensor_Low, Sensor_Dead : exception; begin -- statements which may cause the exceptions exception when E: Sensor_High | Sensor_Low => -- Take some corrective action -- if either sensor_high or sensor_low is raised. -- E contains the exception occurrence when Sensor_Dead => -- sound an alarm if the exception -- sensor_dead is raised end; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 19 - 49

Exception Handling n n when others is used to avoid enumerating all possible exception names Only allowed as the last choice and stands for all exceptions not previously listed declare Sensor_High, Sensor_Low, Sensor_Dead: exception; begin -- statements which may cause exceptions exception when Sensor_High | Sensor_Low => -- take some corrective action when E: others => // last wishes Put(Exception_Name(E)); Put_Line(" caught. Information is available is "); Put_Line(Exception_Information(E)); -- sound an alarm end; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 20 - 49

Exception propagation n If there is no handler in the enclosing block/subprogram/ accept statement, the exception is propagated Ø Ø Ø For a block, the exception is raised in the enclosing block, or subprogram. For a subprogram, it is raised at its point of call For an accept statement, it is raised in both the called and the calling task Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 21 - 49

Last Wishes n n Often the significance of an exception is unknown to the handler which needs to clean up any partial resource allocation Consider a procedure which allocates several devices. procedure Allocate (Number : Devices) is begin -- request each device be allocated in turn -- noting which requests are granted exception when others => -- deallocate those devices allocated raise; -- re-raise the exception end Allocate; n All the resources are allocated or none are Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 22 - 49

Controlled Types n Allow objects to have initialization and finalization routines package Ada. Finalization is pragma Preelaborate(Finalization); type Controlled is abstract tagged private; procedure Initialize(Object : in out Controlled); procedure Adjust(Object : in out Controlled); procedure Finalize(Object : in out Controlled); type Limited_Controlled is abstract tagged private; procedure Initialize(Object : in out Limited_Controlled); procedure Finalize(Object : in out Limited_Controlled); private. . . -- not specified by the language end Ada. Finalization; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 23 - 49

Last Wishes I with Ada. Finalization; use Ada. Finalization; package Last_Wishes is type Finalizer is new Controlled with private; procedure Finalize (O : in out Finalizer); procedure Got_Resource(R: Resource; O : in out Finalizer); private type Finalizer is new Controlled with record Resource 1_Acquired : boolean : = false; . . . end record; end Last_Wishes; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 24 - 49

Last Wishes II with Ada. Text_IO; use Ada. Text_IO; package body Last_Wishes is procedure Finalize (O : in out Finalizer) is begin if Resource 1_Acquired then -- return resources else. . . end if; end Finalize; procedure Get_Resource(R: Resource; O : in out Finalizer) is begin -- set appropriate acquired field to true end Get_Resource; end Last_Wishes; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 25 - 49

Reliable Resource Usaged with Last_Wishes; use Last_Wishes; procedure Reliable_Resource_Usage is final : Finalizer; begin -- get resources etc Get_Resource(R 1, final); -- use resources end Reliable_Resource_Usage; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 26 - 49

Last Wishes and Tasks I n Example: count the number of times two entries are called with Ada. Finalization; use Ada; package Counter is type Task_Last_Wishes is new Finalization. Limited_Controlled with record Count 1, Count 2 : Natural : = 0; end record; procedure Finalize(Tlw : in out Task_Last_Wishes); end Counter; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 27 - 49

Last Wishes and Tasks II with Ada. Integer_Text_IO; use Ada. Integer_Text_IO; with Ada. Text_IO; use Ada. Text_IO; package body Counter is procedure Finalize(Tlw : in out Task_Last_Wishes) is begin Put("Calls on Service 1: "); Put(Tlw. Count 1); Put(" Calls on Service 2: "); Put(Tlw. Count 2); New_Line; end Finalize; end Counter; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 28 - 49

Last Wishes and Tasks III task body Server is Note, can be Last_Wishes : Counter. Task_Last_Wishes; begin used to get last -- initial housekeeping wishes from a loop select procedure as accept Service 1(. . . ) do well. . . end Service 1; Last_Wishes. Count 1 : = Last_Wishes. Count 1 + 1; or accept Service 2(. . . ) do. . . end Service 2; Last_Wishes. Count 2 : = Last_Wishes. Count 2 + 1; or terminate; end select; -- housekeeping end loop; As the task terminates the end Server; finalize procedure is executed Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 29 - 49

Last Wishes — Ada 2005 n n n Ada 2005 has added a new facility When a task terminates, application code can be executed A task can have a specific `termination handler’ or A default handler can be executed The handler knows the cause of termination Ø This includes unhandled exceptions Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 30 - 49

Difficulties with the Ada model of Exceptions n Exceptions and packages Ø Ø n Parameter passing Ø n Exceptions which are raised a package are declared its specification It is not known which subprograms can raise which exceptions The programmer must resort to enumerating all possible exceptions every time a subprogram is called, or use of when others Writers of packages should indicate which subprograms can raise which exceptions using comments Ada only allows strings to be passed to handlers Scope and propagation Ø Ø Ø Exceptions can be propagated outside the scope of their declaration Such exception can only be trapped by when others They may go back into scope again when propagated further up the dynamic chain; this is probably inevitable when using a block structured language and exception propagation Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 31 - 49

Java Exceptions n n Java is similar to Ada in that it supports a termination model of exception handling However, the Java model is integrated into the OO model In Java, all exceptions are subclasses of the predefined class java. lang. Throwable The language also defines other classes, for example: Error, Exception, and Runtime. Exception Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 32 - 49

The Throwable Class Hierarchy Throwable Error Linkage. Error Exception Virtual. Machine. Error Runtime. Errors User-Defined Exceptions unchecked Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 33 - 49

Example public class Integer. Constraint. Error extends Exception { private int lower. Range, upper. Range, value; public Integer. Constraint. Error(int L, int U, int V) { super(); // call constructor on parent class lower. Range = L; upper. Range = U; value = V; } public String get. Message() { return ("Integer Constraint Error: Lower Range " + java. lang. Integer. to. String(lower. Range) + " Upper Range " + java. lang. Integer. to. String(upper. Range) + " Found " + java. lang. Integer. to. String(value)); } } Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 34 - 49

Example Continued import exception. Library. Integer. Constraint. Error; public class Temperature { private int T; public Temperature(int initial) throws Integer. Constraint. Error { // constructor. . . ; } public void set. Value(int V) throws Integer. Constraint. Error {. . . ; } public int read. Value() { return T; } // both the constructor and set. Value can throw an // Integer. Constraint. Error } Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 35 - 49

class Actuator. Dead extends Exception public String get. Message() { return ("Actuator Dead"); } } { class Temperature. Controller { public Temperature. Controller(int T) throws Integer. Constraint. Error { current. Temperature = new Temperature(T); } Temperature current. Temperature; public void set. Temperature(int T) throws Actuator. Dead, Integer. Constraint. Error { // check Actuator current. Temperature. set. Value(T); } } int read. Temperature() { return current. Temperature. read. Value(); }

Declaration n In general, each function must specify a list of throwable checked exceptions throw A, B, C Ø n n in which case the function may throw any exception in this list and any of the unchecked exceptions A, B and C must be subclasses of Exception If a function attempts to throw an exception which is not allowed by its throws list, then a compilation error occurs Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 37 - 49

Throwing an Exception import exception. Library. Integer. Constraint. Error; class Temperature { int T; void check(int value) throws Integer. Constraint. Error { if(value > 100 || value < 0) { throw new Integer. Constraint. Error(0, 100, value); }; } public Temperature(int initial) throws Integer. Constraint. Error // constructor { check(initial); T = initial; } public void set. Value(int V) throws Integer. Constraint. Error { check(V); T = V; } public int read. Value() { return T; } } Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 38 - 49

Exception Handling // given Temperature. Controller TC try { Temperature. Controller TC = new Temperature. Controller(20); TC. set. Temperature(100); // statements which manipulate the temperature } catch (Integer. Constraint. Error error) { // exception caught, print error message on // the standard output System. out. println(error. get. Message()); } catch (Actuator. Dead error) { System. out. println(error. get. Message()); } Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 39 - 49

The catch Statement n n n The catch statement is like a function declaration, the parameter of which identifies the exception type to be caught Inside the handler, the object name behaves like a local variable A handler with parameter type T will catch a thrown object of type E if: Ø Ø n n T and E are the same type, or T is a parent (super) class of E at the throw point This makes the Java exception handling facility very powerful In the last example, two exceptions are derived from the Exception class: Integer. Constraint. Error and Actuator. Dead Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 40 - 49

Catching All try { // statements which might raise the exception // Integer. Constraint. Error or Actuator. Dead } catch(Exception E) { // handler will catch all exceptions of // type exception and any derived type; // but from within the handler only the // methods of Exception are accessible } n n A call to E. get. Message will dispatch to the appropriate routine for the type of object thrown catch(Exception E) is equivalent to Ada's when others Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 41 - 49

Finally n n Java supports a finally clause as part of a try statement The code attached to this clause is guaranteed to execute whatever happens in the try statement irrespective of whether exceptions are thrown, caught, propagated or, indeed, even if there are no exceptions thrown at all try {. . . } catch(. . ) {. . . } finally { // code executed under all circumstances } Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 42 - 49

Recovery Blocks and Exceptions n Remember: ensure <acceptance test> by <primary module> else by <alternative module>. . . else by <alternative module> else error n n Error detection is provided by the acceptance test; this is simply the negation of a test which would raise an exception The only problem is the implementation of state saving and state restoration Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 43 - 49

A Recovery Cache n Consider package Recovery_Cache is procedure Save; -- save volatile state procedure Restore; --restore state procedure Discard; -- discard the state end Recovery_Cache; n The body may require support from the run-time system and possibly even hardware support for the recovery cache Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 44 - 49

Recovery Blocks in Ada procedure Recovery_Block is Primary_Failure, Secondary_Failure, Tertiary_Failure: exception; Recovery_Block_Failure : exception; type Module is (Primary, Secondary, Tertiary); function Acceptance_Test return Boolean is begin -- code for acceptance test end Acceptance_Test; Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 45 - 49

procedure Primary is begin -- code for primary algorithm if not Acceptance_Test then raise Primary_Failure; end if; exception when Primary_Failure => -- forward recovery to return environment -- to the required state raise; when others => -- unexpected error -- forward recovery to return environment -- to the required state raise Primary_Failure; end Primary; -- similarly for Secondary and Tertiary

begin Recovery_Cache. Save; for Try in Module loop begin case Try is when Primary => Primary; exit; when Secondary => Secondary; exit; when Tertiary => Tertiary; end case; exception when Primary_Failure => Recovery_Cache. Restore; when Secondary_Failure => Recovery_Cache. Restore; when Tertiary_Failure => Recovery_Cache. Restore; Recovery_Cache. Discard; raise Recovery_Block_Failure; when others => Recovery_Cache. Restore; Recovery_Cache. Discard; raise Recovery_Block_Failure; end loop; Recovery_Cache. Discard; end Recovery_Block;

Summary I Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 48 - 49

Summary II n n n It is not unanimously accepted that exception handling facilities should be provided in a language The C and the occam 2 languages, for example, have none To sceptics, an exception is a GOTO where the destination is undeterminable and the source is unknown! They can, therefore, be considered to be the antithesis of structured programming This is not the view taken here! Real-Time Systems and Programming Languages: © Alan Burns and Andy Wellings 49 - 49