kodus/file-cache

mkdir cache race condition

Opened this issue · 2 comments

mjac commented

Hi KODUS,

Thank you for your library. I had a failure last night on mkdir($path).

ErrorException Warning: mkdir(): File exists mechanism generic handled false

This occurred in … /vendor/kodus/file-cache/src/FileCache.php in Kodus\Cache\FileCache::mkdir at line 380

        if (!file_exists($parent_path)) {
            $this->mkdir($parent_path); // recursively create parent dirs first
        }
        mkdir($path);
        chmod($path, $this->dir_mode);
    }
}

By inspection, it takes time between file_exists($cache_path) and mkdir($path), especially if $parent_path is missing. If user A and user B are both racing to create this directory then mkdir can be called more than once. In this scenario this will raise an ErrorException warning Warning: mkdir(): File exists

if (! file_exists($cache_path) && file_exists(dirname($cache_path))) {
    $this->mkdir($cache_path); // ensure that the parent path exists
}

The mkdir() function supports recursively creating sub-folders:

mkdir(
    string $directory,
    int $permissions = 0777,
    bool $recursive = false,
    ?resource $context = null
): bool

recursive
If true, then any parent directories to the directory specified will also be created, with the same permissions.

Using mkdir() there will be no need to reinvent how it works with the private FileCache::mkdir() method, and it seems to me it will solve the competing race conditions as well.

mjac commented

This appears to be a great solution