Description
Symfony version(s) affected: 4.*
Description
When using the sortByName
on Finder
there is an unintended file lock in Windows. This
does not release until the application ceases execution. This is due to the __construct
building
an anonymous function and storing at as a property on $sort
.
This gets in the way when doing a recursive directory deletion and causes a Permission Denied
on Windows.
How to reproduce
class FinderBug
{
public function unsortedFiles($path)
{
return iterator_to_array(Finder::create()->files()->ignoreDotFiles(true)->in($path)->depth(0), false);
}
public function sortedFiles($path)
{
return iterator_to_array(
Finder::create()->files()->ignoreDotFiles(true)->in($path)->depth(0)->sortByName(),
false
);
}
public function deleteDirectoryRecursive($directory, bool $sorted = false)
{
$items = $sorted ? $this->sortedFiles($directory) : $this->unsortedFiles($directory);
foreach ($items as $item) {
if ($item->isDir()) {
$this->deleteDirectoryRecursive($item->getPathname(), $sorted);
} else {
@unlink($item->getPathname());
}
}
@rmdir($directory);
}
}
$tempDir = __DIR__ . '/temp';
mkdir($tempDir);
mkdir($tempDir . '/foo');
touch($tempDir.'/foo/1.txt');
$bug = new FinderBug;
$bug->deleteDirectoryRecursive($tempDir . '/foo', false);
$bug->deleteDirectoryRecursive($tempDir, false);
dump(is_dir($tempDir)); // Returns false as expected
mkdir($tempDir);
mkdir($tempDir . '/foo');
touch($tempDir.'/foo/1.txt');
$bug->deleteDirectoryRecursive($tempDir . '/foo', true);
$bug->deleteDirectoryRecursive($tempDir, true);
dump(is_dir($tempDir)); // Return true due to errors.
Possible Solution
Don't store the closure as a property on SortableIterator
. Instead make it a method. It's already noted that this is a potentially slow operation, and I don't believe making this a calculated on the fly value would really make any difference.
Additional context
This is related to a bug that has been chased for months in the Laravel Test Suite for Windows. I'm like 1 of 5 people who develop in PHP on Windows.. so it's been slow moving.