Fast Abstracts Archives . .

FastAbstracts


WHAT IS a
FastAbstract

The History

Archives of
FastAbstracts

ISSRE 2003
ISSRE 2002
ISSRE 2001
ISSRE 2000
ISSRE 1999
ISSRE 1998
FTCS 1999
FTCS 1998



 

 

 
 
Fault Prevention and Removal Using
Consistency Checks

Edgar F. A. Lederer 1 and Romeo A. Dumitrescu 2
Institut für Informatik, Universität Basel
Switzerland

 

Two-Stage Programming (2SP) is an experimental mixed-paradigm (functional/imperative) programming language with strong support for fault prevention and removal [1] through automatic verification of computation results with respect to a given specification. 2SP combines ideas of program verification, run-time checking, and result-checking [2]. The 2SP approach is to coordinate a functional specification of an algorithm by an imperative and optionally parallel/distributed coordination that keeps a strong consistency link with the specification. This approach guarantees: (1) Any inconsistency between coordination and specification is detected during a program execution; (2) Normal termination of a program execution  implies the correctness of obtained results with respect to the specification, for that execution.

Implementation

The current implementation of 2SP is an interpreter (approx. 6,000 lines of SML'97 code, using Standard ML of New Jersey). The interpreter and several different application examples (from simple to complex) are immediately available at http://www.ifi.unibas.ch/Research/Coordination_Models/2sp/2sp.html (without downloading and installing any software). Two complex applications are also detailed in [3, 4].

Basic Features

We describe the basic idea of the 2SP approach through the simple example of Fibonacci numbers to facilitate a fast understanding.

Figure 1 shows the 2SP program for computing the nth Fibonacci number. Fibonacci numbers are described by the standard recursive definition:
f0 = 0, f1 = 1, fi = fi-1 + fi-2   for i > 1.

0 specification (* fib.spc *)
1 n = (* ... *) ;
2 fib (i) = if i = 0 then 0
3           else if i = 1 then 1
4           else if i > 1 then 
5             fib.l1(i-1)+fib.l2(i-2)
6           endif 
7 endspecification

8  coordination (* fib.cor *)
9  A := fib (0) ;
10 B := fib (1) ;
11 for i count n-1 from 2 do     
12   C := fib (i) | fib.l1 <- B ^ fib.l2 <- A ;            
13   A := fib (i-1) <- B ;
14   B := fib (i) <- C 
15 endfor
16 endcoordination

Figure 1: A simple 2SP program.

The first part of a 2SP program is a specification. It is purely functional, store independent. In the above case, the specification directly describes the standard definition. The only unusual aspect of the specification is the presence of the labels l1 and l2 (Line 5). Labels identify different applications of the same function. Their sole purpose is to enable a coordination to uniquely refer to a particular function application in a given definition. The second part of a 2SP program is a coordination. The above coordination maps the recursive definition to the following standard imperative program:

 A := 0; B := 1; i := 2;
 while i < n + 1 do
   C := B + A; A := B; B := C; i := i+1
 end

After termination of execution, store B contains fn for n > 0. It is possible to have several coordinations for a single specification, each of them implementing a different algorithm.

Function Applications    2SP includes three sorts of function applications that make it different from any other programming language:

(1) Full application:
The function applications fib(0) and fib(1) (Lines 9 and 10, respectively) are called full applications. They evaluate by simply following the corresponding recursive function definition. This kind of function application offers the possibility to directly execute the specification (in general not efficient, but useful to validate the specification---rapid prototyping);
 
(2) Fetch Application:
The function applications fib(i-1) <- B (Line 13) and fib(i) <- C (Line 14) are called fetch applications. They evaluate by retrieving the function values fib(i - 1) and fib(i) from stores B and C, respectively (provided these stores contain the required values).
 
(3) Step Application:
The function application on Line 12 is called step application (fib(i) | fib.l1 <- B ^ fib.l2 <- A). It executes a single step of the recursive evaluation. Values fib(i - 1) and fib(i - 2) needed to compute fib(i), for i > 1, are not determined by following again the recur sive definition. They are fetched from the stores B and A, respectively (again, provided these stores contain those values). The utility of the labels is clear now. A step application always refers to a function definition while a fetch application does not.

Assignment commands, full, fetch, and step applications provide the so called consistency link between specification and coordination. This is the base of a powerful mechanism for checking consistency (the consistency checker), described below.

The Consistency Checker    The consistency checker checks, at run-time, whether the stores, from which value retrievals are performed, actually contain the desired values. The computation is aborted and a detailed error message is displayed in case of mismatch. The check is performed by means of symbolic names (called value names) associated with values. For example, the pair (fib,i) is a value name of the value fib(i), where fib is some encoding of the function identifier fib. A corresponding value name is always stored together with the value, after executing an assignment command. When fetching the value from a store, a comparison between the expected value name (provided by the programmer through fetch or step applications) and the stored value name is performed. If both value names agree, the value is fetched, otherwise execution aborts, and an error message is displayed. The error message contains additional information (provided by the value names) and substantially helps debugging. Consider a typical programming error: an error in the range of a loop-counter. For example, if Line 11 is erroneously written: for i count n from 1 do, the following error message is generated:

    Error: value name mismatch in step application
      Line: 12 
        Store: B @ ROOT
          Value name expected: fib (0)
          Value name found:    fib (1)

ROOT is the name of the default processor that runs the program and owns store B. The operator ``@" means ``at". The corresponding standard imperative program (see above), with this error, terminates normally, but produces a wrong result: store B stores fn+1 instead of fn, as required. No need to discuss the consequences of such a wrong, undetected result used later for a critical decision!

Related Work

The result-checking approach is to check the correctness of the final result after execution of a program [2]. The advantage of this approach is that, after the execution, the user knows (with sufficient probability) whether the result is correct or not. Both, result-checking approach and 2SP, use checkers. The checker used by the result-checking approach is external, built separately from the program. The checker used by 2SP is internal, built together with the program. The result-checking approach treats programs as black boxes and, therefore, offers support to only detect errors, but not to locate them. In contrast, 2SP offers strong support to precisely detect and locate errors.

References

[1] Lyu, M. R. "Handbook of Software Reliability Engineering". McGraw-Hill, 1996.

[2] Wassermann, H.; Blum, M. "Software Reliability via Run-Time Result-Checking". Journal of the ACM, 44(6):826--849, November 1997

[3] Lederer, E. F. A.; Dumitrescu, R. A. "Specification-Consistent Coordination Model for Computations," 122-129. Proceedings of the 13th ACM Symposium on Applied Computing (SAC'98). Special Track on Coordination Models, Languages, and Applications. ACM Press, Atlanta, U. S. A., February 27-March 1, 1998.

[4] Lederer, E. F. A.; Dumitrescu, R. A. "Two-Stage Programming," 296-311. Proceedings of the Third Fuji International Symposium on Functional and Logic Programming (FLOPS'98). Kyoto University, Kyoto, JAPAN, April 2-4, 1998.

1.Author contact: Institut für Informatik, Universität Basel, Mittlere Strasse 142, CH-4056 Basel, Switzerland. Phone: ++41-61-3219967. Fax: ++ 41-61-3219915. E-Mail: lederer@ifi.unibas.ch.

2.Author contact: Institut für Informatik, Universität Basel, Mittlere Strasse 142, CH-4056 Basel, Switzerland. Phone: ++41-61-3219967. Fax: ++ 41-61-3219915. E-Mail: romeo@ifi.unibas.ch. Also supported by the Swiss National Science Foundation.