mirror of
https://github.com/django/django.git
synced 2025-06-05 11:39:13 +00:00
Fixed #26691 -- Removed checking for a file's existence before deleting.
File operations always raise a ENOENT error when a file doesn't exist. Checking the file exists before the operation adds a race condition condition where the file could be removed between operations. As the operation already raises an error on a missing file, avoid this race and avoid checking the file exists twice. Instead only check a file exists by catching the ENOENT error.
This commit is contained in:
parent
e3877c53ed
commit
359be1c870
15
django/core/cache/backends/filebased.py
vendored
15
django/core/cache/backends/filebased.py
vendored
@ -35,14 +35,13 @@ class FileBasedCache(BaseCache):
|
|||||||
|
|
||||||
def get(self, key, default=None, version=None):
|
def get(self, key, default=None, version=None):
|
||||||
fname = self._key_to_file(key, version)
|
fname = self._key_to_file(key, version)
|
||||||
if os.path.exists(fname):
|
try:
|
||||||
try:
|
with io.open(fname, 'rb') as f:
|
||||||
with io.open(fname, 'rb') as f:
|
if not self._is_expired(f):
|
||||||
if not self._is_expired(f):
|
return pickle.loads(zlib.decompress(f.read()))
|
||||||
return pickle.loads(zlib.decompress(f.read()))
|
except IOError as e:
|
||||||
except IOError as e:
|
if e.errno == errno.ENOENT:
|
||||||
if e.errno == errno.ENOENT:
|
pass # Cache file doesn't exist.
|
||||||
pass # Cache file was removed after the exists check
|
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
|
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
|
||||||
|
@ -380,15 +380,13 @@ class FileSystemStorage(Storage):
|
|||||||
assert name, "The name argument is not allowed to be empty."
|
assert name, "The name argument is not allowed to be empty."
|
||||||
name = self.path(name)
|
name = self.path(name)
|
||||||
# If the file exists, delete it from the filesystem.
|
# If the file exists, delete it from the filesystem.
|
||||||
# Note that there is a race between os.path.exists and os.remove:
|
# If os.remove() fails with ENOENT, the file may have been removed
|
||||||
# if os.remove fails with ENOENT, the file was removed
|
# concurrently, and it's safe to continue normally.
|
||||||
# concurrently, and we can continue normally.
|
try:
|
||||||
if os.path.exists(name):
|
os.remove(name)
|
||||||
try:
|
except OSError as e:
|
||||||
os.remove(name)
|
if e.errno != errno.ENOENT:
|
||||||
except OSError as e:
|
raise
|
||||||
if e.errno != errno.ENOENT:
|
|
||||||
raise
|
|
||||||
|
|
||||||
def exists(self, name):
|
def exists(self, name):
|
||||||
return os.path.exists(self.path(name))
|
return os.path.exists(self.path(name))
|
||||||
|
@ -48,12 +48,11 @@ class PathNotImplementedStorage(storage.Storage):
|
|||||||
|
|
||||||
def delete(self, name):
|
def delete(self, name):
|
||||||
name = self._path(name)
|
name = self._path(name)
|
||||||
if os.path.exists(name):
|
try:
|
||||||
try:
|
os.remove(name)
|
||||||
os.remove(name)
|
except OSError as e:
|
||||||
except OSError as e:
|
if e.errno != errno.ENOENT:
|
||||||
if e.errno != errno.ENOENT:
|
raise
|
||||||
raise
|
|
||||||
|
|
||||||
def path(self, name):
|
def path(self, name):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
Loading…
x
Reference in New Issue
Block a user