views:

254

answers:

5

I recently ran up against a problem that challenged my programming abilities, and it was a very accidental infinite loop. I had rewritten some code to dry it up and changed a function that was being repeatedly called by the exact methods it called; an elementary issue, certainly. Apache decided to solve the problem by crashing, and the log noted nothing but "spawned child process". The problem was that I never actually finished debugging the issue that day, it cropped up in the afternoon, and had to solve it today.

In the end, my solution was simple: log the logic manually and see what happened. The problem was immediately apparent when I had a log file consisting of two unique lines, followed by two lines that were repeated some two hundred times apiece.

What are some ways to protect ourselves against infinite loops? And, when that fails (and it will), what's the fastest way to track it down? Is it indeed the log file that is most effective, or something else?

Your answer could be language agnostic if it were a best practice, but I'd rather stick with PHP specific techniques and code.

+7  A: 

You could use a debugger such as xdebug, and walk through your code that you suspect contains the infinite loop.

Xdebug - Debugger and Profiler Tool for PHP

You can also set

max_execution_time

to limit the time the infinite loop will burn before crashing.

byte
I'd completely forgotten about xdebug. Thanks!
The Wicked Flea
A: 

write simple code, so bugs will be more apparent? I wonder if your infinite loop is due to some ridiculous yarn-ball of control structures that no human being can possibly understand. Thus of course you f'ed it up.

all infinite loops aren't bad (e.g. while (!quit)).

Dustin Getz
This was in a 100 line codebase; not much there to hang me up on. The trouble was rewriting one routine of an intertwined pair of routines, and reversing the call flow. `a->b->c` became `a<->b`.
The Wicked Flea
+1  A: 

Unit tests might be a good idea, too. You might want to try PHPUnit.

partoa
Good idea, but my code, while testable, would have crashed the unit tests.
The Wicked Flea
+3  A: 

I sometimes find the safest method is to incorporate a limit check in the loop. The type of loop construct doesn't matter. In this example I chose a 'while' statement:

$max_loop_iterations = 10000;
$i=0;
$test=true;
while ($test) {

  if ($i++ == $max_loop_iterations) {
    echo "too many iterations...";
    break;
  }

  ...
}

A reasonable value for $max_loop_iterations might be based upon:

  • a constant value set at runtime
  • a computed value based upon the size of an input
  • or perhaps a computed value based upon relative runtime speed

Hope this helps, - N

nathan
A: 

can you trace execution and dump out a call graph? infinite loops will be obvious, and you can easily pick out the ones that are on purpose (a huge mainloop) vs an accident (local abababa... loop or loop that never returns back to mainloop)

i've heard of software that does this for large complex programs, but i couldn't find a screenshot for you. Someone traced a program like 3dsmax and dumped out a really pretty call graph.

Dustin Getz