From 6c917cbd32b88f6e95e9c8c640a61c4543e37d98 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/_compatibility.py | 2 +- parso/cache.py | 17 ++++++++++++----- parso/file_io.py | 8 ++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/parso/_compatibility.py b/parso/_compatibility.py index 43e1d86a..761763ee 100644 --- a/parso/_compatibility.py +++ b/parso/_compatibility.py @@ -49,7 +49,7 @@ def u(string): FileNotFoundError = FileNotFoundError except NameError: # Python 2.7 (both IOError + OSError) - FileNotFoundError = EnvironmentError + FileNotFoundError = (IOError, OSError) def utf8_repr(func): 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..7b89cea2 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: # TODO Maybe log this? + return False + return True def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self.path)