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

Consistent error logging for cache #8415

Merged
merged 5 commits into from Sep 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 29 additions & 9 deletions src/Psalm/Config.php
Expand Up @@ -35,6 +35,7 @@
use Psalm\Plugin\PluginEntryPointInterface;
use Psalm\Progress\Progress;
use Psalm\Progress\VoidProgress;
use RuntimeException;
use SimpleXMLElement;
use SimpleXMLIterator;
use Throwable;
Expand All @@ -55,7 +56,6 @@
use function clearstatcache;
use function count;
use function dirname;
use function error_log;
use function explode;
use function extension_loaded;
use function file_exists;
Expand Down Expand Up @@ -1013,8 +1013,19 @@ private static function fromXmlAndPaths(
chdir($config->base_dir);
}

if (is_dir($config->cache_directory) === false && @mkdir($config->cache_directory, 0777, true) === false) {
error_log('Could not create cache directory: ' . $config->cache_directory);
if (!is_dir($config->cache_directory)) {
try {
if (mkdir($config->cache_directory, 0777, true) === false) {
// any other error than directory already exists/permissions issue
throw new RuntimeException('Failed to create Psalm cache directory for unknown reasons');
}
} catch (RuntimeException $e) {
if (!is_dir($config->cache_directory)) {
// rethrow the error with default message
// it contains the reason why creation failed
throw $e;
}
}
}

if ($cwd) {
Expand Down Expand Up @@ -2287,20 +2298,29 @@ public static function removeCacheDirectory(string $dir): void
continue;
}

$full_path = $dir . '/' . $object;

// if it was deleted in the meantime/race condition with other psalm process
if (!file_exists($dir . '/' . $object)) {
if (!file_exists($full_path)) {
continue;
}

if (filetype($dir . '/' . $object) === 'dir') {
self::removeCacheDirectory($dir . '/' . $object);
if (filetype($full_path) === 'dir') {
self::removeCacheDirectory($full_path);
} else {
unlink($dir . '/' . $object);
try {
unlink($full_path);
} catch (RuntimeException $e) {
clearstatcache(true, $full_path);
if (file_exists($full_path)) {
// rethrow the error with default message
// it contains the reason why deletion failed
throw $e;
}
}
}
}

reset($objects);

// may have been removed in the meantime
clearstatcache(true, $dir);
if (is_dir($dir)) {
Expand Down
15 changes: 14 additions & 1 deletion src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php
Expand Up @@ -5,6 +5,7 @@
use Psalm\Config;
use Psalm\Internal\Provider\Providers;
use Psalm\Storage\ClassLikeStorage;
use RuntimeException;
use UnexpectedValueException;

use function array_merge;
Expand Down Expand Up @@ -168,7 +169,19 @@ private function getCacheLocationForClass(
$parser_cache_directory = $root_cache_directory . DIRECTORY_SEPARATOR . self::CLASS_CACHE_DIRECTORY;

if ($create_directory && !is_dir($parser_cache_directory)) {
mkdir($parser_cache_directory, 0777, true);
try {
if (mkdir($parser_cache_directory, 0777, true) === false) {
// any other error than directory already exists/permissions issue
throw new RuntimeException('Failed to create ' . $parser_cache_directory . ' cache directory for unknown reasons');
}
} catch (RuntimeException $e) {
// Race condition (#4483)
if (!is_dir($parser_cache_directory)) {
// rethrow the error with default message
// it contains the reason why creation failed
throw $e;
}
}
}

$data = $file_path ? strtolower($file_path) . ' ' : '';
Expand Down
36 changes: 26 additions & 10 deletions src/Psalm/Internal/Provider/FileReferenceCacheProvider.php
Expand Up @@ -5,13 +5,15 @@
use Psalm\Config;
use Psalm\Internal\Codebase\Analyzer;
use Psalm\Internal\Provider\Providers;
use RuntimeException;
use UnexpectedValueException;

use function file_exists;
use function file_put_contents;
use function igbinary_serialize;
use function igbinary_unserialize;
use function is_array;
use function is_dir;
use function is_readable;
use function mkdir;
use function serialize;
Expand Down Expand Up @@ -992,18 +994,32 @@ public function setConfigHashCache(string $hash): void
{
$cache_directory = Config::getInstance()->getCacheDirectory();

if ($cache_directory) {
if (!file_exists($cache_directory)) {
mkdir($cache_directory, 0777, true);
if (!$cache_directory) {
return;
}

if (!is_dir($cache_directory)) {
try {
if (mkdir($cache_directory, 0777, true) === false) {
// any other error than directory already exists/permissions issue
throw new RuntimeException('Failed to create ' . $cache_directory . ' cache directory for unknown reasons');
}
} catch (RuntimeException $e) {
// Race condition (#4483)
if (!is_dir($cache_directory)) {
// rethrow the error with default message
// it contains the reason why creation failed
throw $e;
}
}
}

$config_hash_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CONFIG_HASH_CACHE_NAME;
$config_hash_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CONFIG_HASH_CACHE_NAME;

file_put_contents(
$config_hash_cache_location,
$hash,
LOCK_EX
);
}
file_put_contents(
$config_hash_cache_location,
$hash,
LOCK_EX
);
}
}
15 changes: 14 additions & 1 deletion src/Psalm/Internal/Provider/FileStorageCacheProvider.php
Expand Up @@ -5,6 +5,7 @@
use Psalm\Config;
use Psalm\Internal\Provider\Providers;
use Psalm\Storage\FileStorage;
use RuntimeException;
use UnexpectedValueException;

use function array_merge;
Expand Down Expand Up @@ -168,7 +169,19 @@ private function getCacheLocationForPath(string $file_path, bool $create_directo
$parser_cache_directory = $root_cache_directory . DIRECTORY_SEPARATOR . self::FILE_STORAGE_CACHE_DIRECTORY;

if ($create_directory && !is_dir($parser_cache_directory)) {
mkdir($parser_cache_directory, 0777, true);
try {
if (mkdir($parser_cache_directory, 0777, true) === false) {
// any other error than directory already exists/permissions issue
throw new RuntimeException('Failed to create ' . $parser_cache_directory . ' cache directory for unknown reasons');
}
} catch (RuntimeException $e) {
// Race condition (#4483)
if (!is_dir($parser_cache_directory)) {
// rethrow the error with default message
// it contains the reason why creation failed
throw $e;
}
}
}

if (PHP_VERSION_ID >= 80100) {
Expand Down