How to avoid an infinite loop?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
ashley
Forum Newbie
Posts: 5
Joined: Tue Apr 19, 2005 7:36 pm

How to avoid an infinite loop?

Post by ashley »

I'm currently working on a script to help websites deal with http error codes, it serves up an error page, and records the event with pertinent information, nothing to track a person with, just requested page, referring page, et cetera.

I'm in the middle of trying to create a function to parse the requested url for each "folder" in the requested url to check to see what (if any) resources exist within the url.

If the resource exists, a link to that directory is made, if the resource doesn't exists, it doesn't create a link.

My problem runs into using fopen(). I check each directory with that one function, so, when the script rolls around to the resource with a problem, I get an "infinite loop" (of sorts, apache usually just kills the thread after a while).

The function file_exists() doesn't work, because it uses the file structure, and thus doesn't take .htaccess files into account, which means rewrite_rules which do point to real resources can fail, when they actually do exist "somewhere".

I've also tried fsockopen(), but had some trouble getting the port setting to work properly. I also don't think this is the right path to take.

So, then, how can I get a script, called from an http error page to call itself (which doesn't "exist"), and fail gracefully?

Any suggestions?
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Post some code. (and please read :arrow: Posting Code in the Forums too)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

A properly constructed rewrite rule set for handling the errors can do it by not rewriting the url when the request is internal should handle it. If you used fsockopen() or curl, you could simple request the header information, which will contain the http status code for your script.
malcolmboston
DevNet Resident
Posts: 1826
Joined: Tue Nov 18, 2003 1:09 pm
Location: Middlesbrough, UK

Post by malcolmboston »

im not sure on how this could be implemented atm as im not on my machine but would something like this work.....

Functions Needed

Code: Select all

function GetMicrotime () 
{ 
   list($usec, $sec) = explode(" ", microtime()); 
   return ((float)$usec + (float)$sec); 
}
code to stop looping for too long

Code: Select all

$max_allowed_time = 10; // Allow 10 seconds max
// something to put in the for loop
$query = "SELECT something FROM somewhere";
$result = mysql_query($query) or die (mysql_error()):
//assume we're getting a record
while ($array = mysql_fetch_array($result))
{
  if (!isset($i))
  {
    $i = 1;
  }
  $super_array[$i]['something'] = $array['something'];
  $i++;
}
$count = count($super_array);
// now an example loop firtly getting start time
$start_time = GetMicrotime();
for ($i = 1; $i <= $count; $i++;)
{
  $end_time = GetMicrotime();
  $time_taken = ($end_time - $start_time);
  if ($time_taken >= $max_allowed_time)
  {
    print "Script Exceeded the Max Allowed Execution Time, Execution was suspended";
    break 2;
  }
  else
  {
    print "Something = {$super_array[$i]['something']}<br>\n";
  }
}
in theory, to me at least, this should work

edit: if this works, i may actually implement it into a couple of my projects
User avatar
JayBird
Admin
Posts: 4524
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK
Contact:

Post by JayBird »

Yes, that would work Mal
malcolmboston
DevNet Resident
Posts: 1826
Joined: Tue Nov 18, 2003 1:09 pm
Location: Middlesbrough, UK

Post by malcolmboston »

i was 99% sure it would, just i had to write it in notepad (yuck!)
ashley
Forum Newbie
Posts: 5
Joined: Tue Apr 19, 2005 7:36 pm

Post by ashley »

malcolmboston: that function is fine and all, it just doesn't do what I need it to do. I'm not using a database, I'm opening a file. Openning the file takes too long, because as I said earlier, the script is called from the error page, and is requesting itself with the fopen() call, which means apache will request the page forever.

As far as I can tell, PHP can't stop the execution of something if it takes too long, while loops, do-while loops, for, and foreach all test the expression after (or before) the iteration. If I was to use a loop, I would still test the page once (or not at all), and once is too long, especially in an infinite loop.

As for feyd, how would I construct this rewrite rule to handle internal errors? To be frank, I'm not even sure I know what that first sentence of yours means; I couldn't even wrap my head around that one, links to resources, or even a little pseudo-code would definitely help.

I'd like to stay away from curl, as it's not standard. Currently, fsockopen() is an option, I'm going to look into it more.

Thanks for the help so far guys :)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

my code often will implement varying paths and support levels if curl is available, versus fsockopen.

As for some direction to go on the rewrite rule: RewriteCond is involved.. a lot.
malcolmboston
DevNet Resident
Posts: 1826
Joined: Tue Nov 18, 2003 1:09 pm
Location: Middlesbrough, UK

Post by malcolmboston »

ashley wrote:malcolmboston: that function is fine and all, it just doesn't do what I need it to do. I'm not using a database, I'm opening a file. Openning the file takes too long, because as I said earlier, the script is called from the error page, and is requesting itself with the fopen() call, which means apache will request the page forever.
replace the for loop with the with your own for loop, thought it was rather obvious :/
ashley
Forum Newbie
Posts: 5
Joined: Tue Apr 19, 2005 7:36 pm

Post by ashley »

malcolmboston wrote: replace the for loop with the with your own for loop, thought it was rather obvious :/
I did that, then after some googling, and testing I discovered that the expression, in this case fopen(), is still going to be executed at least once during almost any type of loop, which is too much-especially in an infinite loop.

Hmm... Maybe that's the problem, my use of the term "infinite loop", I didn't mean that a for/foreach/do/do-while loop was repeating forever. I meant that the execution of my fopen() call was being called from my apache error page, which fopen() will eventually call (calling itself), then when the missing page is called, it will generate another error, my http-error page will be called as a replacement, and the cycle will continue on-and-on forever, or close to it :)

Something like this:

http://example.com/path/to/dir/

Let's say that the first two directories exist, but the last one doesn't. fopen() will return success on those, the problem developes when it requests the page that doesn't exist.

So, the page http://example.com/path/to/dir/ places a call for http://example.com/path/to/dir/ which doesn't exist, generating another error, and Apache, not knowing any better, gives my error page as the "replacement", so there is another request for http://example.com/path/to/dir.

And this very annoying cycle continues, and continues, each error page calling the very page it's trying to replace.

I don't even know if I explained it properly, I hope I did though, feel free to flame me if I didn't.

That's my infinite loop, not a control structure infinite loop. If that was the problem, I'm sorry for my mistake, I hope this clarification helps the matter.

I can't stop a loop during the execution of the expression, only in-between each iteration, so even if the values expressed in for() change during an iteration, it will continue to execute until it is time to re-interpret the for() loop.

Don't get me wrong, I could be wrong. If I am, please correct me, it's just what I interpreted.
feyd wrote: As for some direction to go on the rewrite rule: RewriteCond is involved.. a lot.
Thanks for the pointer feyd, never would of thought of looking into mod_rewrite, checking it out currently, I'll post back some responses/remarks when I get a handle on it.
ashley
Forum Newbie
Posts: 5
Joined: Tue Apr 19, 2005 7:36 pm

Post by ashley »

Actually, none of that is needed. I setup a simple if question in the beginning, before the loop is started to check the HTTP_USER_AGENT.

Code: Select all

if (($_SERVER['HTTP_USER_AGENT'] == '') OR ($_SERVER['HTTP_USER_AGENT'] == 'PHP')) {
    die('Error: Infinite loop detected.');
}
It does have it's problems. Depending upon what the php.ini file defines as the HTTP_USER_AGENT. It can vary host-to-host, so checking with a host beforehand is a good thing. PHP is a pretty safe bet. But safe bet isn't a sure thing.

I also assume that somewhere out there, there is a real user agent(browser, bot) that doesn't have anything set for this field either. Haven't met one yet though, so the chances are slim. This also doesn't mean that it's safe either.

It's not perfect, but it's a start.
Post Reply