How to avoid an infinite loop?
Moderator: General Moderators
How to avoid an infinite loop?
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?
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?
- John Cartwright
- Site Admin
- Posts: 11470
- Joined: Tue Dec 23, 2003 2:10 am
- Location: Toronto
- Contact:
Post some code. (and please read
Posting Code in the Forums too)
-
malcolmboston
- DevNet Resident
- Posts: 1826
- Joined: Tue Nov 18, 2003 1:09 pm
- Location: Middlesbrough, UK
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 to stop looping for too long
in theory, to me at least, this should work
edit: if this works, i may actually implement it into a couple of my projects
Functions Needed
Code: Select all
function GetMicrotime ()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}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";
}
}edit: if this works, i may actually implement it into a couple of my projects
-
malcolmboston
- DevNet Resident
- Posts: 1826
- Joined: Tue Nov 18, 2003 1:09 pm
- Location: Middlesbrough, UK
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 :)
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 :)
- feyd
- Neighborhood Spidermoddy
- Posts: 31559
- Joined: Mon Mar 29, 2004 3:24 pm
- Location: Bothell, Washington, USA
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.
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
replace the for loop with the with your own for loop, thought it was rather obvious :/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.
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.malcolmboston wrote: replace the for loop with the with your own for loop, thought it was rather obvious :/
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.
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.feyd wrote: As for some direction to go on the rewrite rule: RewriteCond is involved.. a lot.
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.
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.
Code: Select all
if (($_SERVER['HTTP_USER_AGENT'] == '') OR ($_SERVER['HTTP_USER_AGENT'] == 'PHP')) {
die('Error: Infinite loop detected.');
}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.