Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LocalFilesystemAdapter::fileSize(),fileExists(),directoryExists and possible other method uses cached values #1826

Open
Nicolai- opened this issue Oct 31, 2024 · 0 comments

Comments

@Nicolai-
Copy link

Bug Report

Q A
Flysystem Version 3.29.1
Adapter Name LocalFilesystemAdapter
Adapter version 3.29.0

Summary

Repeat calls to fileSize() will return the same value if the file has been modified(by another process) between calls as the value is cached and not cleared by calling clearstatcache().

The is more or less the same issue that has previously been fixed in #1035 for file size.

The same issue is present if another process deletes a file or a directory, then concurrent calls to fileExists() or directoryExists() will be cached if it has existed on disk during the process. So it will continue to return true, even if the file/director has been deleted on disk.

Looking at https://www.php.net/manual/en/function.clearstatcache.php
Then this could be an issue for some of the other methods as well lastModified() and possible others

In v1 fileSize(), getTimestamp() was part of the getMetaData() method which called clearstatcache()
And the way to differentiate between a file and directory was to check the type inside the metadata

How to reproduce

Belows simulates what happens inside LocalFileSystemAdapterfileSize::fileSize() when another process writes to a file

FileSize:

$file = 'fileSize.txt';
touch($file);
for($i = 0; $i < 5; $i++)
{
    clearstatcache();
    $beforeSize = filesize($file);

    exec("echo 1 >> {$file}"); // This simulates another process that writes to the file

    //clearstatcache(); // Uncomment to get the change in filesize
    $afterSize = filesize($file);

    if($beforeSize === $afterSize)
     {
        $strMessage = 'No change in file size.';
     }
    else
    {
        $strMessage = 'File size changed.';
    }

    echo "{$strMessage} Before: {$beforeSize} After: {$afterSize}".PHP_EOL;

    sleep(1);
}

FileExists:

$file = 'filesize.txt';
touch($file);

$isFileBefore = is_file($file);

exec("rm -f {$file}");

$isFileAfter = is_file($file);

echo 'Before: '.($isFileBefore ? 'Exists' : 'Does Not Exist').' After: '.($isFileAfter ? 'Exists' : 'Does Not Exist').PHP_EOL;

clearstatcache();

echo "Clear stat cache".PHP_EOL;
echo "File exists: ".(is_file($file) ? 'Yes' : 'No').PHP_EOL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant