anteatersa
anteatersa

Reputation: 1518

Is there anyway to set a timeout for a file_exists or any other function?

I am running a website where we are serving a large amount of files from a folder mounted over Fuse (cloudfuse - a Rackspace Cloudfiles container), it works wonderfully most of the time however every now and again the Fuse connection stalls and all my Apache processes hang waiting for a file_exists() function to return.

My question, is there anyway to set a timeout for a specific function or to use another function to check if the file exists but return with false if function takes longer than x seconds?

Upvotes: 5

Views: 2656

Answers (5)

johnjg12
johnjg12

Reputation: 1103

Similar to Peters answer, I used that to figure out something simple/elegant (this probably won't work 1:1 on windows though):

$command = "timeout 10 ls '{$file}'";
exec($command, $output, $exit_code);
if($exit_code !== 0) {
    // non 0 exit code means it failed. 
    // Exit code will be 124 if the ls command timed out 
    // (didn't return after 10 seconds in this case)
    echo "Failed to check if file exists, ls command exited with code '{$exit_code}': `{$command}` Output: ".implode("\n", $output));
    // do error handling...
}

See linux man page for timeout command for more info. The exit code will be 124 when it times out: "If the command times out, and --preserve-status is not set, then exit with status 124."

If the file exists and is readable (user running this has permissions to see the file) then the exit code will be 0. Otherwise it will likely be 2, as demonstrated below (run from linux)

# ls not_a_file
ls: cannot access not_a_file: No such file or directory
# echo "exit code for last command was $?"
exit code for last command was 2

This also works on stale NFS mounts, which was my problem, when using file_exists or just ls on that when mount is hung results in an "infinite" time to return.

Upvotes: 0

Peter
Peter

Reputation: 16943

I think file_exists() is only simple function, and is not intended for such operations.

Workaround #1 (quite elegant)

  • make a batch file which is checking is file exists
  • use system() function to execute your batch file and parse result

Workaround #2 (simpler, not elegant at all)

  • make a script file_exists.php?file=... returning string "TRUE" or "FALSE" if file $_GET['file'] exists. Set time_limit in this file to 1 second.
  • get results using fsockopen('http://localhost/file_exists.php?file='.$file, ..., ..., 2) and parse results. (empty or FALSE = file doesn't exists). 2 is fsockopen's timeout. You can use system('/usr/bin/php /path/to/your/script.php') as well

Upvotes: 3

ajreal
ajreal

Reputation: 47321

I think you can run a script to scan all files in the mounted cloudfuse,
(typically will be a cronjob)

then stored the results into a storage (memcache, database, etc...),
subsequently your PHP script can make use on the results

in order to keep the scan result up-to-date,
you can add-in hook to update the results when files updated / added / deleted

Upvotes: 1

Peter
Peter

Reputation: 16943

You can give a try to this:

  function file_exists_timeout($file, $timeout) {
      // try with both, as i mentioned in comment
      // this is just a shot :( maybe it will works for you
      ini_set('default_socket_timeout', $timeout);
      stream_set_timeout($timeout); 

      $file = fopen($file, 'r');
      if($file) {
          fclose($file);
          return true;
     }else{
          return false;
     }
   }

but i am not sure it will work for you.

Upvotes: 1

Tim
Tim

Reputation: 1899

You can use PHP's set_time_limit to limit the execution time of the "parent" script. http://php.net/manual/en/function.set-time-limit.php

Upvotes: -1

Related Questions