diff options
author | Marti Raudsepp <marti@juffo.org> | 2022-12-13 11:20:25 +0200 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-12-13 19:29:15 +0100 |
commit | 32268456d6494483f9a737dc7c32bbbf1eceab8c (patch) | |
tree | 2bba75bf71f911c549f811cb7c4fcb0d92ec30b6 | |
parent | 1d0fa848e084cad62d0bb6bde3b51e4862558e57 (diff) | |
download | django-32268456d6494483f9a737dc7c32bbbf1eceab8c.tar.gz |
Fixed #34209 -- Prevented FileBasedCache.has_key() crash caused by a race condition.
-rw-r--r-- | django/core/cache/backends/filebased.py | 5 | ||||
-rw-r--r-- | tests/cache/tests.py | 6 |
2 files changed, 9 insertions, 2 deletions
diff --git a/django/core/cache/backends/filebased.py b/django/core/cache/backends/filebased.py index 631da49444..215fefbcc0 100644 --- a/django/core/cache/backends/filebased.py +++ b/django/core/cache/backends/filebased.py @@ -90,10 +90,11 @@ class FileBasedCache(BaseCache): def has_key(self, key, version=None): fname = self._key_to_file(key, version) - if os.path.exists(fname): + try: with open(fname, "rb") as f: return not self._is_expired(f) - return False + except FileNotFoundError: + return False def _cull(self): """ diff --git a/tests/cache/tests.py b/tests/cache/tests.py index 937a55acc5..c4d4522514 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -1762,6 +1762,12 @@ class FileBasedCacheTests(BaseCacheTests, TestCase): with open(cache_file, "rb") as fh: self.assertIs(cache._is_expired(fh), True) + def test_has_key_race_handling(self): + self.assertIs(cache.add("key", "value"), True) + with mock.patch("builtins.open", side_effect=FileNotFoundError) as mocked_open: + self.assertIs(cache.has_key("key"), False) + mocked_open.assert_called_once() + @unittest.skipUnless(RedisCache_params, "Redis backend not configured") @override_settings( |