There has actually been a lot of work over the years on termination analysis.
If memory serves me correctly, in order to define a function at all in the
Boyer-Moore theorem prover (back in the 1970s) it had to be (made) obvious
to the verifier that the function would terminate. Typically, there had to
be a measure (by default, size) on the arguments such that any recursive call
was ‘simpler’.
An obvious violation of this is when the arguments of a recursive call are
identical to the arguments in the head.
It’s true that you don’t get OTP without infinite loops, but
loop(State) → … loop(NewState)
normally doesn’t pass the same state in the recursive call.
It’s good to get to know a wide range of debugging tools, but the sooner any
bug is found, the better for everyone.
The following AWK script might be a useful approximation of this bug check:
/^[a-zA-Z.@][a-zA-Z0-9.@][(].[)] ->/ {
head = $0
sub(/ ->.$/, “”, head)
gsub(/ /, “”, head)
defn = FNR
}
match($0, /[^a-zA-Z0-9.@][a-zA-Z.@][a-zA-Z0-9.@_][(].[)][,;. ](%.)?$/) {
x = substr($0, RSTART+1, RLENGTH-1)
sub(/[,;. ](%.)?$/, “”, x)
gsub(/ /, “”, x)
if (x == head) {
print FILENAME “: possible infinite loop”, defn, FNR
}
}
It’s not perfect, but it was good enough to experiment with and look for
false positives. server_loop/2 in zip.erl of stdlib has a nice set of
false positives. And of course it is confused by ‘when’.
Here’s an interesting case.
stat_loop(M, Old) →
timer:sleep(2000),
case statistics(run_queue) of
Old →
stat_loop(M, Old);
NewLoad →
M ! {node(), load, NewLoad}, %% async
stat_loop(M, NewLoad)
end.
This is an infinite recursion with an unchanged state.
It’s basically spinning until the run queue changes.
What I find interesting here is that a quick debugging hack
has drawn my attention to code that is dubious for another
reason: a magic delay. Why 2000? Why not 200 or 20000?
Is this a good pick in the majority of cases? It surely
deserves a comment.
A slightly more sophisticated version of this – based on
the abstract syntax after macro processing – looks as though
it might be useful.