review articles

doi:10.1145/1941487.1941509 set of queries: to solve the problem In contrast to popular belief, proving we would need to invent a method ca- pable of accurately answering either termination is not always impossible. “terminates” or “doesn’t terminate” when given any program drawn from By Byron Cook, Andreas Podelski, this set. Turing’s result tells us that and Andrey Rybalchenko any tool that attempts to solve this problem will fail to return a correct answer on at least one of the inputs. No number of extra processors nor terabytes of storage nor new sophisti- Proving cated will lead to the devel- opment of a true oracle for program termination. Unfortunately, many have drawn Program too strong of a conclusion about the prospects of automatic program ter- mination proving and falsely believe we are always unable to prove termi- Termination nation, rather than more benign con- sequence that we are unable to always prove termination. Phrases like “but that’s like the termination problem” are often used to end discussions that might otherwise have led to viable par- tial solutions for real but undecidable The program termination problem, also known problems. While we cannot ignore termination’s undecidability, if we as the uniform , can be defined as develop a slightly modified problem follows: statement we can build useful tools. In our new problem statement we will Using only a finite amount of time, determine still require that a termination prov- whether a given program will always finish running ing tool always return answers that or could execute forever. are correct, but we will not necessarily require an answer. If the termination This problem rose to prominence before the prover cannot prove or disprove termi- invention of the modern computer, in the era of nation, it should return “unknown.” a Using only a finite amount of time, Hilbert’s Entscheidungsproblem: the challenge to determine whether a given program formalize all of mathematics and use algorithmic will always finish running or could means to determine the validity of all statements. execute forever, or return the answer “unknown.” In hopes of either solving Hilbert’s challenge, or showing it impossible, logicians began to search key insights for possible instances of undecidable problems.  For decades, the same method was used 38 for proving termination. It has never been Turing’s proof of termination’s undecidability is applied successfully to large programs. er b p oo the most famous of those findings.  A deep theorem in mathematical logic, w based on Ramsey’s theorem, holds the e

The termination problem is structured as an infinite key to a new method. tth y Ma b

a In English: “decision problem.”  The new method can scale to large on b There is a minor controversy as to whether or not Turing proved the undecidability in38. Technically programs because it allows for the ti ra

he did not, but termination’s undecidability is an easy consequence of the result that is proved. A modular construction of termination st 36 simple proof can be found in Strachey. arguments. Illu

88 communications of the acm | may 2011 | vol. 54 | no. 5 credit tk ma y 2011 2011 y | v o l. 54 54 l. | n o . 5 5 . | c ommun ic at i ons of the a the of ons c m

89 review articles

This problem can clearly be solved, provable using termination proving adapting the techniques to other do- as we could simply always return “un- techniques.12,29 With every month, we mains. We also discuss current work known.” The challenge is to solve this now see more powerful applications and possible avenues for future inves- problem while keeping the occurrenc- of automatic termination proving. As tigation. Concepts and strategies will es of the answer “unknown” to within an example, recent work has demon- be introduced informally, with cita- a tolerable threshold, in the same way strated the utility of automatic ter- tions to original papers for those inter- that we hope Web browsers will usu- mination proving to the problem of ested in more detail. Several sidebars ally succeed to download Web pages, showing concurrent algorithms to be are included for readers with back- although we know they will sometimes non-blocking.20 With further research grounds in mathematical logic. fail. Note that the principled use of and development, we will see more unknown in tools attempting to solve powerful and more scalable tools. Disjunctive Termination Arguments undecidable or intractable problems We could also witness a shift in the Thirteen years after publishing his is increasingly common in computer power of software, as techniques from original undecidability result, Turing science; for example, in program anal- termination proving could lead to proposed the now classic method of ysis, type systems, and networking. tools for other problems of equal dif- proving program termination.39 His In recent years, powerful new ter- ficulty. Whereas in the past a software solution divides the problem into two mination tools have emerged that re- developer hoping to build practical parts: turn “unknown” infrequently enough tools for solving something related to Termination argument search: Find that they are useful in practice.35 These termination might have been fright- a potential termination argument in termination tools can automatically ened off by a colleague’s retort “but the form of a function that maps every prove or disprove termination of many that’s like the termination problem,” program state to a value in a math- famous complex examples such as perhaps in the future the developer ematical structure called a well-order. Ackermann’s function or McCarthy’s will instead adapt techniques from We will not define well-orders here, 91 function as well as moderately sized within modern termination provers the reader can assume for now that we industrial examples such as Windows in order to develop a partial solution are using the natural numbers (a.k.a. device drivers. Furthermore, entire to the problem of interest. the positive integers). families of industrially useful termi- The purpose of this article is to fa- Termination argument checking: nation-like properties—called live- miliarize the reader with the recent Proves the termination argument to ness properties—such as “Every call to advances in program termination be valid for the program under con- lock is eventually followed by a call proving, and to catalog the underly- sideration by proving that result of the to unlock” are now automatically ing techniques for those interested in function decreases for every possible program transition. That is, if f is the termination argument and the pro- gram can transition from some state s Turing’s Classic Method to state s¢, then f(s) > f( s¢). (Readers with a background in logic and Disjunctive may be interested in the formal expla- nation contained in the sidebar here.) A well-order can be thought of as a Well-Foundness terminating program—in the exam- Formally proving program termination amounts to proving the program’s transition ple of the natural numbers, the pro- relation R to be well-founded. If (S, ≥) is a well-order then > is a well-founded relation. gram is one that counts from some Furthermore, any map f into S defines a well-founded relation, by lifting > viaf , that is, {(s, t) | f (s) > f (t)}. Turing’s method39 of proving a program’s transition relation R initial value in the natural numbers well-founded amounts to finding a mapf into a well-order, which defines a termination down to 0. Thus, no matter which ini- argument T = {(s, t) | f (s) > f (t)}. To prove the validity of T we must show R ⊆ T. From the tial value is chosen the program will well-foundedness of T and the fact that every sub-relation of a well-founded relation is still terminate. Given this connection well-founded follows that R is well-founded. In this article we are using the phrase disjunctive termination argument to refer to between well-orders and terminat- 31 a disjunctively well-founded transition invariant. This is a finite unionT 1 ∪ . . . ∪ Tn of ing programs, in essence Turing is well-founded relations that contains R+, which is the transitive closure of the transition proposing that we search for a map relation of the program, as a superset, such as, R+ ⊆ T1 ∪ . . . ∪ Tn. from the program we are interested in Usually, each T1, . . . , Tn will be constructed as above via some map into a well-order. Note that the non-reflexive transitive closure (the + inR +) is crucial. It is not sufficient proving terminating into a program to show that R ⊆ T1 ∪ . . . ∪ Tn,, as the union of well-founded relations is not guaranteed known to terminate such that all steps to be well-founded. It is the transitive closure that makes checking the subset inclusion in the first program have analogous more difficult in practice. The recent approaches for proving termination for general programs3,4,9,12,14,32 are steps in the second program. This based on the proof rule of disjunctively well-founded transition invariants. The proof map to a well-order is usually called a rule itself is based on Ramsey’s theorem,34 and it has been developed in the effort to progress measure or a ranking function give a logical foundation to the termination analysis based on size-change graphs.24 The principle expressed by the proof rule appears implicitly already in previously developed in the literature. Until recently, all termination algorithms for rewrite systems and logic and functional programs, see known methods of proving termina- refs10, 15, 17, 24. tion were in essence minor variations on the original technique.

90 communications of the acm | may 2011 | vol. 54 | no. 5 review articles

The problem with Turing’s meth- rem,34 and it has been developed in code fragment in Figure 1. In this code od is that finding a single, or mono- the effort to give a logical foundation the collection of user-provided input is lithic, ranking function for the whole to the termination analysis based on performed via the function input(). program is typically difficult, even for size-change graphs.24 We will assume the user always enters simple programs. In fact, we are often The principle it expresses appears a new value when prompted. Further- forced to use ranking functions into implicitly in previously developed ter- more, we will assume for now that vari- well-orders that are much more com- mination algorithms for rewrite sys- ables range over possibly negative in- plex than the natural numbers. Luck- tems, logic, and functional programs, tegers with arbitrary precision (that is, ily, once a suitable ranking function see refs 10,15,17,24. mathematical integers as opposed to has been found, checking validity is in The advantage to the new style of 32-bit words, 64-bit words, and so on). practice fairly easy. termination argument is that it is Before reading further, please answer The key trend that has led toward usually easier to find, because it can the question: “Does this program ter- current progress in termination prov- be expressed in small, mutually in- minate, no matter what values the user ing has been the move away from the dependent pieces. Each piece can be gives via the input() function?” The search for a single ranking function found separately or incrementally us- answer is given below.c and toward a search for a set of rank- ing various known methods for the Using Turing’s traditional method ing functions. We think of the set as a discovery of monolithic termination we can define a ranking function from choice of ranking functions and talk arguments. As a trade-off, when using program variables to the natural num- about a disjunctive termination argu- a disjunctive termination argument, a bers. One ranking function that will ment. This terminology refers to the more difficult validity condition must work is 2x + y, though there are many proof rule of disjunctively well-found- be checked. This difficulty can be mit- others. Here we are using the formula ed transition invariants.31 The recent igated thanks to recent advances in as- 2x + y as shorthand for a function approaches for proving termination sertion checking tools (as discussed in that takes a program configuration for general programs3,4,9,12,14,26,32 are a later section). as its input and returns the natural based on this proof rule. The proof Example using a monolithic termina- number computed by looking up the rule itself is based on Ramsey’s theo- tion argument. Consider the example value of x in the memory, multiply- ing that by 2 and then adding in y’s Figure 1. Example program. value—thus 2x + y represents a map- ping from program configurations to

1 x : = input(); natural numbers. This ranking func- 2 y : = input(); tion meets the constraints required 3 while x > 0 and y > 0 do to prove termination: the valuation of 4 if input() = 1 then 2x + y when executing at line 9 in the 5 x : = x – 1; 6 y : = y + 1; program will be strictly one less than 7 else its valuation during the same loop 8 y : = y – 1; iteration at line 4. Furthermore, we 9 fi know the function always produces 10 done natural numbers (thus it is a map into User-supplied inputs are gathered via calls to the function input(). We assume that the variables a well-order), as 2x + y is greater than range over integers with arbitrary precision (in other words, not 64-bit or 32-bit integers). Assuming 0 at lines 4 through 9. that the user always eventually enters in a value when prompted via input(), does the program terminate for all possible user-supplied inputs? (The answer is provided in a footnote below.) Automatically proving the valid- ity of a monolithic termination argu- ment like 2x + y is usually easy using tools that check verification condi- Figure 2. Example program. tions (for example, Slam2). However, as mentioned previously, the actual search for a valid argument is fa- 1 x := input(); mously tricky. As an example, consid- 2 y := input(); 3 while x > 0 and y > 0 do er the case in Figure 2, where we have 4 if input () = 1 then replaced the command “y := y + 1;” 5 x := x × 1; in Figure 1 with “y := input();”. In 6 y := input(); 7 else this case no function into the natural 8 y := y – 1; numbers exists that suffices to prove 9 fi termination; instead we must resort 10 done to a lexicographic ranking function This program is similar to Figure 1 where the command “y := y + 1;” replaced with (a ranking function into ordinals, a “y := input();”. No ranking function into the natural numbers exists that can prove the more advanced well-order than the termination of this program. naturals).

c terminate. does program The

may 2011 | vol. 54 | no. 5 | communications of the acm 91 review articles

Example using a disjunctive termi- gram in Figure 2, where we replaced “y ther x goes down by at least one and nation argument. Following the trend := y + 1;” with “y := input();.” On x is greater than 0 or y goes down by toward the use of disjunctive termina- every possible unrolling of the loop we at least one and y is greater than 0. tion arguments, we could also prove will still see that either x or y has gone Yet, the program does not guarantee the termination of Figure 1 by defin- down and is larger than 0. termination. As an example input se- ing an argument as the unordered To see why we cannot use the same quence that triggers non-termination, finite collection of measures x and validity check for disjunctive termina- consider 5, 5, followed by 1, 0, 1, 0, 1, y. The termination argument in this tion arguments as we do for monolith- 0, …. If we consider all possible unroll- case should be read as: ic ones, consider the slightly modified ings of the loop, however, we will see example in Figure 3. For every single that after two iterations it is possible x goes down by at least 1 and is larger than 0. iteration of the loop it is true that ei- (in the case that the user supplied the or y goes down by at least 1 and is larger than 0 Figure 3. Another example program.

We have constructed this termina- tion argument with two ranking func- 1 x := input(); 2 y := input(); tions: x and y. The use of “or” is key: 3 while x > 0 and y > 0 do the termination argument is modu- 4 if input() = 1 then lar because it is easy to enlarge using 5 x := x – 1; 6 y := y + 1; additional measures via additional 7 else uses of “or.” As an example, we could 8 x := x + 1; enlarge the termination argument 9 y := y – 1; by adding “or 2w − y goes down by 10 fi 11 done at least 1 and is greater than 1,000.” Furthermore, as we will discuss later, Does it terminate for all possible user-supplied inputs? independently finding these pieces of the termination argument is easier in practice than finding a single mono- lithic ranking function. Figure 4. Example program with an assertion statement in line 3. The expert reader will notice the relationship between our disjunctive 1 if y ≥ 1 then termination argument and complex 2 while x > 0 do lexicographic ranking functions. The 3 assert (y ≥ 1); 4 x := x – y; advantage here is that we do not need 5 done to find an order on the pieces of the 6 fi argument, thus making the pieces of the argument independent from one another. The difficulty with disjunctive ter- Figure 5. Encoding of termination argument validity. mination arguments in comparison to monolithic ones is that they are more 1 copied := 0; difficult to prove valid: for the benefit 2 x := input(); of modularity we pay the price in the 3 y := input(); fact that the termination arguments 4 while x > 0 and y > 0 do must consider the transitions in all 5 if copied = 1 then 6 assert (oldx ≥ x + 1 and oldx > 0); possible loop unrollings and not just 7 elsif input() = 1 then single passes through a loop. That is to 8 copied := 1; say: the disjunctive termination argu- 9 oldx := x; 10 oldy := y; ment must hold not only between the 11 fi states before and after any single itera- 12 if input() = 1 then tion of the loop, but before and after 13 x := x – 1; any number of iterations of the loop 14 y := y + 1; 15 else (one iteration, two iterations, three 16 y := y – 1; iterations, and so on). This is a much 17 fi more difficult condition to automati- 18 done cally prove. In the case of Figure 1 we Encoding of termination argument validity using the program from Figure 1 and the termination can prove the more complex condition argument “x goes down by at least one and is larger than 0.” The black code comes directly from using techniques described later. Figure 1. The code in red implements the encoding of validity with an assertion statement. Note that this same termination ar- gument now works for the tricky pro-

92 communications of the acm | may 2011 | vol. 54 | no. 5 review articles inputs 1 and 0 during the two loop iterations) that neither x nor y went down, and thus the disjunctive termi- nation argument is not valid for the Implementation Strategies program in Figure 3. Here, we give a brief summary of implementation strategies based on disjunctive termination arguments deployed by the recent termination checkers: Refinement:9,14 In Cook et al.,14 the termination argument begins with ø. We first Argument Validity Checking attempt to prove that R+ ⊆ ø. When this proof fails, rank function synthesis is applied While validity checking for disjunc- to the witness, thus giving a refinement T1 to the argument, which is then rechecked tive termination arguments is more R+ ⊆ ø ∪ T1. This process is repeated until a valid argument is found or a real counterexample is found. difficult than checking for mono- In Chawdhary et al.,9 the termination argument T is constructed following the lithic arguments, we can adapt the structure of the transition relation R = R1 ∪ . . . ∪ Rm by using a ranking function problem statement such that recently synthesis procedure, which is used to compute a well-founded overapproximation developed tools for proving the valid- WF(X) of a binary relation X. The initial candidate T = WF(R1) ∪ . . . ∪ WF (Rm) is extended with WF (WF (Ri) ° Rj) and so on until the fixpoint is reached. ity of assertions in programs (such as Variance analysis:3,32 As described in some detail in this article, the approach from Slam2). Berdine et al.3 and Podelski et al.32 uses program transformations and abstract An assertion statement can be put interpretation for invariants to compute an overapproximation T1; T2, . . . , Tn such that R+ ⊆ T1 ∪ T2 . . . ∪ Tn. It then uses rank function synthesis to check that each Ti is well- in a program to check if a condition founded. is true. For example, assert(y ≥ 1); In contrast to the refinement-based methods, variance analysis always terminates, checks that y ≥ 1 after executing the but may return “don’t know” in cases when a refinement-based method succeeds. command. We can use an assertion checking tool to formally investigate at compile time whether the conditions an assertion statement to check the coding given in Cook et al.14 The new passed to assertion statements always termination argument always holds code (introduced as a part of the en- evaluate to true. For example, most as- between the current state and the re- coding) is given in red, whereas the sertion checking tools will be able to corded state. If the assertion checker original program from Figure 1 is in prove the assert statement at line 3 can prove the assert cannot fail, it has black. We make use of an extra call to in Figure 4 never fails. Note that com- proved the validity of the termination input() to decide when the unroll- pile-time assertion checking is itself argument. We can use encoding tricks ing begins. The new variables oldx an , although it to force the assertion checker to con- and oldy are used for recording a state. is technically in an easier class of dif- sider all possible unrollings. Note that the assertion checker must ficulty than termination.d Figure 5 offers such an example, consider all values possibly returned The reason that assertion checking where we have used the termination by input() during its proof, thus the is so important to termination is the argument “x goes down by at least one proof of termination is valid for any validity of disjunctive termination ar- and x is greater than 0” using the en- starting position. This has the effect of guments can be encoded as an asser- tion statement, where the statement Figure 6. Encoding of termination argument validity using previous program. fails only in the case that the termina- tion argument is not valid. Once we are 1 copied := 0; given an argument of the form T1 or T2 2 x := input(); or … or Tn, to check validity we simply 3 y := input(); want to prove the following statement: 4 while x > 0 and y > 0 do 5 if copied = 1 then Each time an execution passes 6 assert( (oldx ≥ x + 1 and oldx > 0) through one state and then through 7 or 8 (oldy ≥ y + 1 and oldy > 0) another one, T1 or T2 or … or Tn holds 9 ); between these two states. That is, there 10 elsif input() = 1 then does not exist a pair of states, one be- 11 copied := 1; ing reachable from the other, possibly 12 oldx := x; via the unrolling of a loop, such that 13 oldy := y; 14 fi neither T1 nor T2 nor … nor Tn holds be- 15 if input() = 1 then tween this pair of states. 16 x := x – 1; This statement can be verified a 17 y := y + 1; 18 else program transformation where we 19 y := y – 1; introduce new variables into the pro- 20 fi gram to record the state before the 21 done unrolling of the loop and then use Encoding of termination argument validity using the program from Figure 1 and the termination argument “x goes down by at least one and is larger than 0 or y goes down by at least one and is larger than 0.” The black code comes directly from Figure 1. The code in red implements d Checking validity of an assertion statement is the encoding of validity with an assertion statement. an undecidable but co-recursively enumerable problem, whereas termination is neither r.e. nor co-r.e. problem.

may 2011 | vol. 54 | no. 5 | communications of the acm 93 review articles

considering any possible unrolling of the paths. A plethora of recently devel- we reached the current state from the the loop. After some state has been re- oped techniques now make this pos- recorded one. That is: this is the unroll- corded, from this point out the termi- sible. Many recent assertion checkers ing found that demonstrates that the nation argument is checked using the are designed to produce a path to a bug assertion statement can fail. What we recorded state and the current state. In in the case that the assertion statement know is that the termination argument this case the assertion can fail, mean- cannot be proved. For example, a path does not currently cover the case where ing that the termination argument is leading to the assertion failure is 1 → this path is repeated forever. not valid. 2 → 3 → 4 → 5 → 7 → 8 → 9 → 10 → See Figure 6 for a version using the If we were to attempt to check this 11 → 12 → 16 → 17 → 4 → 5 → 6. This same encoding, but with the valid ter- condition in a naïve way (for example, path can be broken into parts, each mination argument: by simply executing the program) we representing different phases of the ex- would never find a proof for all but the ecution: the prefix-path 1 → 2 → 3 → x goes down by at least 1 and is larger than 0 most trivial of cases. Thus, assertion 4 is the path from the program initial or checkers must be cleverly designed to state to the recorded state in the failing y goes down by at least 1 and is larger than 0. find proofs about all possible execu- pair of states. The second part of the tions without actually executing all of path 4 → 5 → . . . 5 → 6 represents how This assertion cannot fail. The fact that it cannot fail can be proved by a Figure 7. Program prepared for abstract interpretation. number of assertion verification tools.

1 copied := 0; Finding Termination Arguments 2 x := input(); We have examined how we can check 3 y := input(); a termination argument’s validity via 4 while x > 0 and y > 0 do a translation to a program with an as- 5 if copied = 1 then 6 skip; sertion statement. We now discuss 7 elsif input() = 1 then known methods for finding monolith- 8 copied := 1; ic termination arguments. 9 oldx := x; 10 oldy := y; Rank function synthesis. In some 11 fi cases simple ranking functions can 12 if input() = 1 then be automatically found. We call a 13 x := x – 1; ranking function simple if it can be 14 y := y + 1; 15 else defined by a linear arithmetic expres- 16 y := y – 1; sion (for example, −3x = −2y + 100). 17 fi The most popular approach for find- 18 done ing this class of ranking function uses a result from Farkas16 together with tools for solving linear constraint sys- Figure 8. Example C loop over a linked-list data-structure with fields next and data. tems. (See Colón and Sipma11 or Polel- ski and Rybalchecko30 for examples of tools using Farkas’ lemma.) Many c = head; other approaches for finding rank- while (c != NULL) { if (c – >next != NULL && c – > next – >data == 5) { ing functions for different classes of t = c – >next; programs have been proposed (see c–>next = c –> next –>next; refs1, 6−8, 19, 37). Tools for the synthesis of free(t); ranking functions are sometimes ap- } c = c–>next; plied directly to programs, but more } frequently they are used (on small and simplified program fragments) internally within termination proving tools for suggesting the single ranking Figure 9. Example program illustrating nontermination. functions that appear in a disjunctive termination argument.

1 x := 10; Termination analysis. Numerous 2 while x > 9 do approaches have been developed for 3 x := x – 232; finding disjunctive termination argu- 4 done ments in which—in effect—the valid- Example program demonstrating nontermination when variables range over fixed-width numbers. The ity condition for disjunctive termina- program terminates if x ranges over arbitrary size integers, but repeatedly visits the state where x = tion arguments is almost guaranteed 10 in the case that x ranges over 32-bit unsigned numbers. to hold by construction. In some cas- es—for example, Berdine et al.3—to prove termination we need only check

94 communications of the acm | may 2011 | vol. 54 | no. 5 review articles that the argument indeed represents a Recall Figure 5, which encoded the set of measures. In other cases, such invalid termination argument for the as Lee et al.24 or Manolios and Vroon,26 program in Figure 1, and the path lead- the tool makes a one-time guess as to ing to the failure of the assertion: is 1 the termination argument and then → 2 → 3 → 4 → 5 → 7 → 8 → 9 → 10 checks it using techniques drawn from In recent years, → 11 → 12 → 16 → 17 → 4 → 5 → 6. abstract interpretation. powerful new Recall this path represents two phases Consider the modified program of the program’s execution: the path in Figure 7. The termination strat- termination tools to the loop, and some unrolling of the egy described in Berdine et al.3 and have emerged that loop such that the termination con- Podelski and Rybalchenko32 essen- dition doesn’t hold. In this case the tially builds a program like this and return “unknown” path 4 → 5 → . . . 6 represents how we then applies a custom program analy- reached the second failing state from sis to find the following candidate ter- infrequently enough the first. This is a counterexample to mination argument: that they are useful the validity of the termination argu- ment, meaning that the current ter- (copied ≠ 1) or in practice. mination argument does not take this (oldx ≥ x + 1, oldx > 0, oldy path and others like it into account. > 0, x ≥ 0, y > 0) or If the path can be repeated forever (oldx ≥ x, oldy ≥ y + 1, oldx during the program’s execution then > 0, oldy > 0, x > 0, y ≥ 0) we have found a real counterexample. Known approaches (for example, Gup- for the program at line 4—meaning we ta et al.21) can be used to try and prove could pass this complex expression to this path can be repeated forever. In the assertion at line 4 in Figure 7 and this case, however, we know that the know that the assertion cannot fail. path cannot be repeated forever, as We know this statement is true of any y is decremented on each iteration unrolling of the loop in the original through the path and also constrained Figure 1. What remains is to prove that via a conditional statement to be posi- each piece of the candidate argument tive. Thus this path is a spurious coun- represents a measure that decreases— terexample to termination and can here we can use rank function synthe- be ruled out via a refinement to the sis tools to prove that oldx > x + 1 and termination argument. Again, using oldx > 0 . . . represents the measure rank function synthesis tools we can based on x. If each piece between the automatically find a ranking function ors in fact represents a measure (with that demonstrates the spuriousness of the exception of copied ≠ 1 which this path. In this case a rank function comes from the encoding) then we synthesis tool will findy , meaning that have proved termination. the reason this path cannot be repeat- One difficulty with this style of ter- ed forever is that “y always goes down mination proving is that, in the case by at least one and is larger than 0.” We that the program doesn’t terminate, can then refine the current termina- the tools can only report “unknown,” tion argument used in Figure 5: as the techniques used inside the ab- stract interpretation tools have lost x goes down by at least 1 and is larger than 0 so much detail that it is impossible with the larger termination argument: to find a non-terminating execution x goes down by at least 1 and is larger than 0 from the failed proof and then prove it or non-terminating. The advantage when y goes down by at least 1 and is larger than 0 compared to other known techniques is it is much faster. We can then check the validity of Finding arguments by refinement. this termination argument using a tool Another method for discovering a ter- such as IMPACT on the program in Fig- mination argument is to follow the ap- ure 6. IMPACT can prove this assertion proach of Cook et al.14 or Chawdhary never fails, thus proving the termina- et al.9 and search for counterexamples tion of the program in Figure 1. to (possibly invalid) termination argu- ments and then refine them based on Further Directions new ranking functions found via the With fresh advances in methods for counterexamples. proving the termination of sequen-

may 2011 | vol. 54 | no. 5 | communications of the acm 95 review articles

tial programs that operate over math- automatically discover the shapes of programs use variables that range ematical numbers, we are now in the data-structures) and then to create over fixed-width numbers, such as position to begin proving termination new auxiliary variables in the program 32-bit integers or 64-bit floating- of more complex programs, such as that track the sizes of those data struc- point numbers, with the possibility those with dynamically allocated data tures, thus allowing for arithmetic of overflow or underflow. If a program structures, or multithreading. Fur- ranking functions to be more easily uses only fixed-width numbers and thermore, these new advances open expressed (examples include refs4,5,25). does not use dynamically allocated up new potential for proving proper- The difficultly with this approach is memory, then termination proving is ties beyond termination, and finding that we are now dependent on the ac- decidable (though still not easy). In conditions that would guarantee ter- curacy and scalability of current shape this case we simply need to look for a mination. We now discuss these av- analysis tools—to date the best known repeated state, as the program will di- enues of future research and develop- shape analysis tool40 supports only verge if and only if there exists some ment in some detail. lists and trees (cyclic and acyclic, sin- state that is repeated during execu- Dynamically allocated heap. Con- gly and doubly linked) and scales only tion. Furthermore, we cannot ignore sider the C loop in Figure 8, which to relatively simple programs of size the fixed-width semantics, as over- walks down a list and removes links less than 30,000 LOC. Furthermore, flow and underflow can cause non- with data elements equaling 5. Does the auxiliary variables introduced by termination in programs that would this loop guarantee termination? methods such as Magill et al.25 some- otherwise terminate, an example is What termination argument should times do not track enough informa- included in Figure 9. Another com- we use? tion in order to prove termination (for plication when considering this style The problem here is that there are example, imagine a case with lists of of program is that of bit-level opera- no arithmetic variables in the program lists in which the sizes of the nested tions, such as left- or right-shift. from which we can begin to construct lists are important). In order to im- Binary executables. Until now we an argument—instead we would want prove the state of the art for termina- have discussed proving termination of to express the termination argument tion proving of programs using data programs at their source level, perhaps over the lengths of paths to NULL via structures, we must develop better in C or Java. The difficulty with this the next field. Furthermore, the pro- methods of finding arguments over strategy is the compilers that then take grammer has obviously intended for data structure shapes, and we must these source programs and convert this loop to be used on acyclic sin- also improve the accuracy and scal- them into executable artifacts can in- gly linked lists, but how do we know ability of existing shape analysis tools. troduce termination bugs that do not that the lists pointed to by head will Bit vectors. In the examples used exist in the original source program. always be acyclic? The common solu- until now we have considered only Several potential strategies could help tion to these problems is to use shape variables that range over mathemati- mitigate this problem: We might try to analysis tools (which are designed to cal numbers. The reality is that most prove termination of the executable binaries instead of the source level Figure 10. Example of multi-threaded terminating producer/consumer program. programs, or we might try to equip the compiler with the ability to prove 1 while x > 0 do that the resulting binary program pre- 2 x := x – 1; 1 while y > 0 do serves termination, perhaps by first 3 lock(lck) 2 lock (lck) proving the termination of the source 4 b := x; 3 y:=b; 5 unlock(lck) 5 unlock(lck) program and then finding a map from 6 done 6 done the binary to the source-level program and proving that the composition with To prove that the thread on the left terminates we must assume that the thread on the right always the source-level termination argument calls unlock when needed. To prove that the thread on the right always calls unlock when needed, we must prove that the thread on the left always calls unlock when needed, and so on. forms a valid termination argument for the binary-level program. Non-linear systems. Current ter- mination provers largely ignore non- Figure 11. Collatz program. linear arithmetic. When non-linear updates to variables do occur (for ex- 1 while x > 1 do ample x := y * z;), current termina- 2 if x is divisible by 2 then tion provers typically treat them as 3 x := x=2; if they were the instruction x := in- 4 else 5 x := 3x + 1; put();. This modification is sound— 6 fi meaning when the termination prover 7 done returns the answer “terminating,” we

We assume that x ranges over all natural numbers with arbitrary precision (that is, neither 64-bit know the proof is valid. Unfortunately, vectors nor 32-bit vectors). A proof of this program’s termination or non-termination is not known. this method is not precise: the treat- ment of these commands can lead to the result “unknown” for programs

96 communications of the acm | may 2011 | vol. 54 | no. 5 review articles that actually terminate. Termination representing its executions, but this provers are also typically unable to find approach does not scale well to larger or check non-linear termination argu- programs. The challenge is to develop ments (x2, for example) when they are automatic methods of finding non-cir- required. Some preliminary efforts in cular rely-guarantee termination argu- this direction have been made,1,6 but With fresh ments. Recent steps20 have developed these techniques are weak. To improve advances in heuristics that work for non-blocking the current power of termination prov- algorithms, but more general tech- ers, further developments in non-lin- methods for niques are still required. ear reasoning are required. proving the Advanced programming features. Concurrency. Concurrency adds an The industrial adoption of high-level extra layer of difficulty when attempt- termination programming features such as virtual ing to prove program termination. The functions, inheritance, higher-order problem here is that we must consider of sequential functions, or closures make the task of all possible interactions between con- programs that proving industrial programs more of a currently executing threads. This is es- challenge. With few exceptions (such pecially true for modern fine-grained operate over as Giesl et al.18), this area has not been concurrent algorithms, in which mathematical well studied. threads interact in subtle ways through Untyped or dynamically typed pro- dynamically allocated data structures. numbers, we are grams also contribute difficulty when Rather than attempting to explicitly now in the position proving termination, as current ap- consider all possible interleavings of proaches are based on statically dis- the threads (which does not scale to to begin proving covering data-structure invariants and large programs) the usual method for finding arithmetic measures in order proving concurrent programs correct termination of to prove termination. Data in untyped is based on rely-guarantee or assume- more complex programs is often encoded in strings, guarantee style of reasoning, which using pattern matching to marshal considers every thread in isolation programs. data in and out of strings. Termination under assumptions on its environ- proving tools for JavaScript would be ment and thus avoids reasoning about especially welcome, given the havoc thread interactions directly. Much of that nonterminating JavaScript causes the power of a rely-guarantee proof daily for Web browsers. system (such as Jones22 and Misra and Finding preconditions that guarantee Chandy28) comes from the cyclic proof termination. In the case that a program rules, where we can assume a proper- does not guarantee termination from ty of the second thread while proving all initial configurations, we may want property of the first thread, and then to automatically discover the condi- assume the recently proved property tions under which the program does of the first thread when proving the as- guarantee termination. That is, when sumed property of the second thread. calling some function provided by a This strategy can be extended to live- library: what are the conditions under ness properties using induction over which the code is guaranteed to return time, for example, Gotsman et al.20 and with a result? The challenge in this McMillan.27 area is to find the right precondition: As an example, consider the two the empty precondition is correct but code fragments in Figure 10. Imagine useless, whereas the weakest precon- that we are executing these two frag- dition for even very simple programs ments concurrently. To prove the ter- can often be expressed only in com- mination of the left thread we must plex domains not supported by today’s prove that it does not get stuck waiting tools. Furthermore, they should be for the call to lock. To prove this we computed quickly (the weakest pre- can assume the other thread will al- condition expressible in the target log- ways eventually release the lock—but ic may be too expensive to compute). to prove this of the code on the right Recent work has shown some prelimi- we must assume the analogous prop- nary progress in this direction.13,33 erty of the thread on the left, and so Liveness. We have alluded to the on. In this case we can certainly just connection between liveness prop- consider all possible interleavings of erties and the program termination the threads, thus turning the concur- problem. Formally, liveness proper- rent program into a sequential model ties expressed in temporal logics can

may 2011 | vol. 54 | no. 5 | communications of the acm 97 review articles

be converted into questions of fair ter- Conclusion 19. Giesl, J. Thiemann, R., Schneider-Kamp, P. and Falke, S. Automated termination proofs with AProVE. In mination—termination proving were This article has surveyed recent ad- Proceedings of RTA, 2004. certain non-terminating executions vances in program termination prov- 20. Gotsman, A., Cook, B., Parkinson, M. and Vafeiadis, V. Proving that non-blocking algorithms don’t block. In are deemed unfair via given fairness ing techniques for sequential pro- Proceedings of POPL, 2009. constraints, and thus ignored. Cur- grams, and pointed toward ongoing 21. Gupta, A., Henzinger, T., Majumdar, R., Rybalchenko, A., and Xu, R. Proving non-termination. In Proceedings of rent tools, in fact, either perform this work and potential areas for future POPL, 2008. reduction, or simply require the user to development. The hope of many tool 22. Jones, C.B. Tentative steps toward a development method for interfering programs. ACM Trans. Program. express liveness constraints directly as builders in this area is that the current Lang. Syst., 1983. the set of fairness constraints.12,29 Nei- and future termination proving tech- 23. Jula, H., Tralamazza, D., Zamfir, C. and Candea, G. Deadlock immunity: Enabling systems to defend ther approach is optimal: the reduc- niques will become generally avail- against deadlocks. In Proceedings of OSDI, 2008. 24. lee, C.S., Jones, N.D. and Ben-Amram, A.M.. The tion from liveness to fairness is ineffi- able for developers wishing to directly size-change principle for program termination. In cient in the size of the conversion, and prove termination or liveness. We also Proceedings of POPL, 2001. 25. Magill, S., Berdine, J., Clarke, E. and Cook, B. fairness constraints are difficult for hope that termination-related appli- Arithmetic strengthening for shape analysis. In humans to understand when used di- cations—such as detecting livelock at Proceedings of SAS, 2007. 26. Manolios, P. and Vroon, D. Termination analysis with rectly. An avenue for future work would runtime or Wang’s tiling problem— calling context graphs. In Proceedings of CAV, 2006. be to directly prove liveness properties, will also benefit from these advances. 27. McMillan, K.L. Circular compositional reasoning about liveness. In Proceedings of CHARME, 1999. perhaps as an adaption of existing ter- 28. Misra, J and Chandy, K.M. Proofs of networks of mination proving techniques. Acknowledgments processes. IEEE Trans. Software Eng., 1981. 29. Pnueli, A., Podelski, A., and Rybalchenko, A. Separating Dynamic analysis and crash dumps The authors would like to thank Lu- fairness and well-foundedness for the analysis of fair for liveness bugs. In this article we have cas Bourdeaux, Abigail See, Tim Har- discrete systems. In Proceedings of TACAS, 2005. 30. Podelski, A, and Rybalchenko, A. A complete method focused only on static, or compile-time, ris, Ralf Herbrich, Peter O’Hearn, and for the synthesis of linear ranking functions. In proof techniques rather than tech- Hongseok Yang for their reading of Proceedings of VMCAI, 2004. 31. Podelski, A, and Rybalchenko, A. Transition invariants. niques for diagnosing divergence dur- early drafts of this article and sugges- In Proceedings of LICS, 2004. ing execution. Some effort has been tions for improvement. 32. Podelski, A. and Rybalchenko, A. Transition predicate abstraction and fair termination. In Proceedings of placed into the area of automatically POPL, 2005. 33. Podelski, A., Rybalchenko, A., and Wies, T. Heap detecting deadlock during execution References assumptions on demand. In Proceedings of CAV, 2008. time. With new developments in the 1. Babic, D., Hu, A.J., Rakamaric, Z., and Cook, B. Proving 34. Ramsey, F. On a problem of formal logic. London Math. area of program termination proving termination by divergence. In SEFM, 2007. Soc., 1930. 2. Ball, T., Bounimova, E., Cook, B., Levin, V., Lichtenberg, 35. Stix, G. Send in the Terminator. Scientific American we might find that automatic methods J., McGarvey, C., Ondrusek, B., Rajamani, S.K. and (Nov. 2006). Ustuner, A. Thorough static analysis of device drivers. 36. Strachey, C. An impossible program. Computer of discovering livelock could also now In Proceedings of EuroSys, 2006. Journal, 1965. be possible. Temporary modifications 3. Berdine, J., Chawdhary, A., Cook, B., Distefano, D. 37. Tiwari, A. Termination of linear programs. In to scheduling, or other techniques, and O’Hearn, P. Variance analyses from invariance Proceedings of CAV, 2004. analyses. In Proceedings of POPL, 2007. 38. Turing, A. On computable numbers, with an application might also be employed to help pro- 4. Berdine, J., Cook, B., Distefano, D. and O’Hearn, P. to the Entscheidungsproblem. London Mathematical Society, 1936. grams not diverge even in cases where Automatic termination proofs for programs with shape-shifting heaps. In Proceedings of CAV, 2006. 39. Turing, A. Checking a large routine. In Report of a Conference on High Speed Automatic Calculating they do not guarantee termination or 5. Bouajjani, A., Bozga, M., Habermehl, P., Iosif, R., Moro, Machines, 1949. P. and Vojnar, T. Programs with lists are counter other liveness properties. Some pre- 40. Yang, H., Lee, O., Berdine, J., Calcagno, C., Cook, B., automata. In Proceedings of CAV, 2006. liminary work has begun to emerge Distefano, D. and O’Hearn, P. Scalable shape analysis 6. Bradley, A., Manna, Z. and Sipma, H. Termination of for systems code. In Proceedings of CAV, 2008. in this area (see Jula et al.23) but more polynomial programs. In Proceedings of VMCAI, 2005. 7. Bradley, A., Manna, Z. and Sipma, H.B. Linear ranking work is needed. with reachability. In Proceedings of CAV, 2005. Scalability, performance, and preci- 8. Bradley, A., Manna, Z. and Sipma, H.B. The polyranking Byron Cook is a Principal Researcher at Microsoft’s principle. In Proceedings of ICALP, 2005. research laboratory at Cambridge University, and a sion. Scalability to large and complex professor of at Queen Mary, University 9. Chawdhary, C., Cook, B., Gulwani, S., Sagiv, M. and of London, England. programs is currently a problem for Yang, H. Ranking abstractions. In Proceedings of ESOP, 2008. modern termination provers—cur- Andreas Podelski is a professor of computer science at 10. Codish, M., Genaim, S., Bruynooghe, M., Gallagher, J. the University of Freiburg, Germany. rent techniques are known, at best, to and Vanhoof, W. One loop at a time. In Proceedings of WST, 2003. scale to simple systems code of 30,000 Andrey Rybalchenko is a professor of computer science 11. Colón, M. and Sipma, H. Synthesis of linear ranking at the Technische Universität München, Germany. lines of code. Another problem we face functions. In Proceedings of TACAS, 2001. is one of precision. Some small pro- 12. Cook, B., Gotsman, A., Podelski, A., Rybalchenko, A. and Vardi, M. Proving that programs eventually do grams currently cannot be proved ter- something good. In Proceedings of POPL, 2007. minating with existing tools. Turing’s 13. Cook, B., Gulwani, S., Lev-Ami, T., Rybalchenko, A. and Sagiv, M. Proving conditional termination. In undecidability result, of course, states Proceedings of CAV, 2008. that this will always be true, but this 14. Cook, B., Podelski, A. and Rybalchenko, A. Termination does preclude us from improving pre- proofs for systems code. In Proceedings of PLDI, 2006. 15. Dershowitz, N., Lindenstrauss, N., Sagiv, Y. and cision for various classes of programs Serebrenik, A. A general framework for automatic and concrete examples. The most fa- termination analysis of logic programs. Appl. Algebra Eng. Commun. Comput., 2001. mous example is that of the Collatz’ 16. Farkas, J. Uber die Theorie der einfachen problem, which amounts to proving Ungleichungen. Journal für die reine und angewandte Mathematik, 1902. the termination or non-termination 17. Geser, A. Relative termination. PhD dissertation, 1990. of the program in Figure 11. Currently 18. Giesl, J., Swiderski, S., Schneider-Kamp, P. and Thiemann, R. Automated termination analysis no proof of this program’s termination for Haskell: From term rewriting to programming behavior is known. languages. In Proceedings of RTA, 2006. © 2011 ACM 0001-0782/11/05 $10.00

98 communications of the acm | may 2011 | vol. 54 | no. 5