Skip to content

Commit

Permalink
Do not use recursive mkdir() - it's not thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 14, 2020
1 parent 85683bb commit 96d8202
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 15 deletions.
36 changes: 24 additions & 12 deletions src/Cache/FileCacheStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ public function __construct(string $directory)
$this->directory = $directory;
}

public function makeRootDir(): void
{
$this->makeDir($this->directory);
}

private function makeDir(string $directory): void
{
if (is_dir($directory)) {
return;
}

$result = @mkdir($directory, 0777, true);
$result = @mkdir($directory, 0777);
if ($result === false) {
clearstatcache();
if (is_dir($directory)) {
Expand All @@ -41,7 +46,7 @@ private function makeDir(string $directory): void
public function load(string $key, string $variableKey)
{
return (function (string $key, string $variableKey) {
$filePath = $this->getFilePath($key);
[,, $filePath] = $this->getFilePaths($key);
if (!is_file($filePath)) {
return null;
}
Expand All @@ -66,8 +71,9 @@ public function load(string $key, string $variableKey)
*/
public function save(string $key, string $variableKey, $data): void
{
$path = $this->getFilePath($key);
$this->makeDir(dirname($path));
[$firstDirectory, $secondDirectory, $path] = $this->getFilePaths($key);
$this->makeDir($firstDirectory);
$this->makeDir($secondDirectory);

$tmpPath = sprintf('%s/%s.tmp', $this->directory, Random::generate());
$tmpSuccess = @file_put_contents(
Expand All @@ -92,16 +98,22 @@ public function save(string $key, string $variableKey, $data): void
}
}

private function getFilePath(string $key): string
/**
* @param string $key
* @return array{string, string, string}
*/
private function getFilePaths(string $key): array
{
$keyHash = sha1($key);
return sprintf(
'%s/%s/%s/%s.php',
$this->directory,
substr($keyHash, 0, 2),
substr($keyHash, 2, 2),
$keyHash
);
$firstDirectory = sprintf('%s/%s', $this->directory, substr($keyHash, 0, 2));
$secondDirectory = sprintf('%s/%s', $firstDirectory, substr($keyHash, 2, 2));
$filePath = sprintf('%s/%s.php', $secondDirectory, $keyHash);

return [
$firstDirectory,
$secondDirectory,
$filePath,
];
}

}
8 changes: 7 additions & 1 deletion src/Command/CommandHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Nette\Schema\Processor;
use Nette\Utils\Strings;
use Nette\Utils\Validators;
use PHPStan\Cache\FileCacheStorage;
use PHPStan\Command\Symfony\SymfonyOutput;
use PHPStan\Command\Symfony\SymfonyStyle;
use PHPStan\DependencyInjection\ContainerFactory;
Expand Down Expand Up @@ -208,7 +209,7 @@ public static function begin(

if (!isset($tmpDir)) {
$tmpDir = sys_get_temp_dir() . '/phpstan';
if (!@mkdir($tmpDir, 0777, true) && !is_dir($tmpDir)) {
if (!@mkdir($tmpDir, 0777) && !is_dir($tmpDir)) {
$errorOutput->writeLineFormatted(sprintf('Cannot create a temp directory %s', $tmpDir));
throw new \PHPStan\Command\InceptionNotSuccessfulException();
}
Expand Down Expand Up @@ -327,6 +328,11 @@ public static function begin(
}
}

$fileCacheStorage = $container->getService('cacheStorage')->makeRootDir();
if ($fileCacheStorage instanceof FileCacheStorage) {
$fileCacheStorage->makeRootDir();
}

/** @var FileFinder $fileFinder */
$fileFinder = $container->getByType(FileFinder::class);

Expand Down
2 changes: 1 addition & 1 deletion src/Testing/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static function getContainer(): Container

if (!isset(self::$containers[$cacheKey])) {
$tmpDir = sys_get_temp_dir() . '/phpstan-tests';
if (!@mkdir($tmpDir, 0777, true) && !is_dir($tmpDir)) {
if (!@mkdir($tmpDir, 0777) && !is_dir($tmpDir)) {
self::fail(sprintf('Cannot create temp directory %s', $tmpDir));
}

Expand Down
7 changes: 6 additions & 1 deletion tests/bootstrap.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php declare(strict_types = 1);

use PHPStan\Cache\FileCacheStorage;
use PHPStan\Testing\TestCase;

error_reporting(E_ALL);
Expand All @@ -21,4 +22,8 @@ public function doFoo($i)
}');

TestCase::getContainer();
$container = TestCase::getContainer();
$fileCacheStorage = $container->getService('cacheStorage');
if ($fileCacheStorage instanceof FileCacheStorage) {
$fileCacheStorage->makeRootDir();
}

0 comments on commit 96d8202

Please sign in to comment.