Skip to content

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

Closed
@Nicolai-

Description

@Nicolai-

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;

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @Nicolai-

      Issue actions

        LocalFilesystemAdapter::fileSize(),fileExists(),directoryExists and possible other method uses cached values · Issue #1826 · thephpleague/flysystem