From 7742d8a903d5daaadd23f278672dd102a4c0cc31 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Sun, 10 Jul 2022 09:23:13 +0200 Subject: [PATCH] use lock to fix race condition --- .../Internal/Provider/ParserCacheProvider.php | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index 85c0c06c42c..755a064a807 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -8,9 +8,14 @@ use RuntimeException; use function error_log; +use function fclose; use function file_get_contents; use function file_put_contents; use function filemtime; +use function filesize; +use function flock; +use function fopen; +use function fread; use function gettype; use function igbinary_serialize; use function igbinary_unserialize; @@ -28,9 +33,12 @@ use function trigger_error; use function unlink; use function unserialize; +use function usleep; use const DIRECTORY_SEPARATOR; use const E_USER_ERROR; +use const LOCK_EX; +use const LOCK_SH; use const SCANDIR_SORT_NONE; /** @@ -184,7 +192,28 @@ private function getExistingFileContentHashes(): array $file_hashes_path = $root_cache_directory . DIRECTORY_SEPARATOR . self::FILE_HASHES; if ($root_cache_directory && is_readable($file_hashes_path)) { - $hashes_encoded = (string) file_get_contents($file_hashes_path); + $fp = fopen($file_hashes_path, 'r'); + $max_wait_cycles = 5; + $has_lock = false; + while ($max_wait_cycles > 0) { + if (flock($fp, LOCK_SH)) { + $has_lock = true; + break; + } + $max_wait_cycles--; + usleep(50000); + } + + if (!$has_lock) { + fclose($fp); + error_log('Could not acquire lock for content hashes file'); + $this->existing_file_content_hashes = []; + + return []; + } + + $hashes_encoded = fread($fp, filesize($file_hashes_path)); + fclose($fp); if (!$hashes_encoded) { error_log('Unexpected value when loading from file content hashes'); @@ -281,7 +310,8 @@ public function saveFileContentHashes(): void file_put_contents( $file_hashes_path, - json_encode($file_content_hashes) + json_encode($file_content_hashes), + LOCK_EX ); }