From 32268456d6494483f9a737dc7c32bbbf1eceab8c Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Tue, 13 Dec 2022 11:20:25 +0200 Subject: [PATCH] Fixed #34209 -- Prevented FileBasedCache.has_key() crash caused by a race condition. --- django/core/cache/backends/filebased.py | 5 +++-- 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(