Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

file_exists doesn't seem to work correctly

I've got a php-script that i want to execute, only if an other instance of the script isn't already running. I've got this code:

$lockfile = __DIR__.'/lock.file';

if(file_exists($lockfile) == false)
{
    echo 'no lockfile. Job will execute.';
    $handle = fopen($lockfile, 'x') or die('Cannot open file:  '.$lockfile);
    $data = 'This is the lockfile';
    fwrite($handle, $data);
    fclose($lockfile);

    createLinks();

    unlink($lockfile);
}
else
{
    echo 'Lockfile present, job will not execute. Please try again later';
}

But it doesn't correctly check if the file exists. If i call the script with my browser, the lock.file is correctly created (i can see it with ftp), and afterwards deleted. However, i still can run the script multiple times simultaneously. If i create a lock.file myself with ftp, it doesn't execute the script. I've been searching for hours now, what can it be? Maybe i'm stupid, but i think this should work, right?

Edit: Jep, flock did it. Thanks very much! Final code:

$lockfile = __DIR__.'/lock.file';
$handle = fopen($lockfile, "x");

if(flock($handle, LOCK_EX))
{
    echo 'no lockfile. Job will execute.';

    $data = 'This is the lockfile';
    fwrite($handle, $data);

    createLinks();

    fclose($lockfile);  
    unlink($lockfile);
}
else
{
    echo 'Lockfile present, job will not execute. Please try again later';
}
like image 879
wjhulzebosch Avatar asked Oct 04 '22 20:10

wjhulzebosch


2 Answers

From the documentation of file_exists:

Note: The results of this function are cached. See clearstatcache() for more details.`

and:

You should also note that PHP doesn't cache information about non-existent files. So, if you call file_exists() on a file that doesn't exist, it will return FALSE until you create the file. If you create the file, it will return TRUE even if you then delete the file. However unlink() clears the cache automatically

Try changing your function to:

if(file_exists($lockfile) == false)
{
    clearstatcache();
    ...

Have a look at clearstatcache().

like image 111
Marko D Avatar answered Oct 10 '22 01:10

Marko D


I've waisted today half a day dealing with almost the same problem as yours one. My PHP code also used file locks and had file_exists() call in it. And I was having the same problem with "strange" file_exists() results. I was completely confused when I changed the usage of files (to gain a lock) to the usage of the DB - a lock corresponded to a row in a table. The results were fully the same - I tried to launch the code concurrently in different tabs of a browser, but I still failed to gain the lock.

And then I realized what was the real reason of such strange behavior. In my case (it looks like that your case was the same) the main problem was in the fact that the script was launched "multiple times simultaneously" but in one browser. But requests were processed not concurrently but sequentially. A good explanation of such effect was given here: https://stackoverflow.com/a/3623584/1758680

So as all requests became sequentially - each request was waiting a preceding one to end. Each lock was released before the next script would start and try to gain the lock.

like image 27
Sergii Golubev Avatar answered Oct 10 '22 02:10

Sergii Golubev