From 2356d56eb857f53af3c84f3f6ff2ecd4c37b0294 Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Mon, 1 Jun 2020 16:27:33 +0300 Subject: [PATCH] Global cache lock, more strict error handling --- parso/cache.py | 17 ++++++++++++----- parso/file_io.py | 8 ++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/parso/cache.py b/parso/cache.py index 04e9ce7f..c0f516f1 100644 --- a/parso/cache.py +++ b/parso/cache.py @@ -100,8 +100,7 @@ def _get_cache_clear_lock(cache_path = None): collection once a day (can be configured in _CACHE_CLEAR_THRESHOLD). """ cache_path = cache_path or _get_default_cache_path() - - return FileIO(os.path.join(cache_path, "{}-cache-lock".format(_VERSION_TAG))) + return FileIO(os.path.join(cache_path, "PARSO-CACHE-LOCK")) parser_cache = {} @@ -226,7 +225,10 @@ def clear_inactive_cache( file.stat().st_atime + _CACHED_FILE_MAXIMUM_SURVIVAL <= time.time() ): - os.remove(file.path) + try: + os.remove(file.path) + except OSError: # silently ignore all failures + continue else: return True @@ -238,8 +240,13 @@ def _remove_cache_and_update_lock(cache_path = None): clear_lock_time is None # first time or clear_lock_time + _CACHE_CLEAR_THRESHOLD <= time.time() ): - if clear_inactive_cache(cache_path = cache_path): - lock._touch() + if not lock._touch(): + # First make sure that as few as possible other cleanup jobs also + # get started. There is still a race condition but it's probably + # not a big problem. + return False + + clear_inactive_cache(cache_path = cache_path) def _get_hashed_path(hashed_grammar, path, cache_path=None): directory = _get_cache_directory_path(cache_path=cache_path) diff --git a/parso/file_io.py b/parso/file_io.py index 2218dd70..34b41ecc 100644 --- a/parso/file_io.py +++ b/parso/file_io.py @@ -27,8 +27,12 @@ def _touch(self): try: os.utime(self.path, None) except FileNotFoundError: - file = open(self.path, 'a') - file.close() + try: + file = open(self.path, 'a') + file.close() + except (OSError, IOError): # TODO Maybe log this? + return False + return True def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self.path)