[2.1.x] Fixed #29890 -- Fixed FileSystemStorage crash if concurrent saves try to create the same directory.
Regression in 632c4ffd9cb1da273303bcd8005fff216506c795. Backport of 98ef3829e96ebc73d4d446f92465e671ff520d2b from master.
This commit is contained in:
parent
0f02d71995
commit
cd7d6c8af7
@ -234,9 +234,9 @@ class FileSystemStorage(Storage):
|
||||
os.umask(old_umask)
|
||||
else:
|
||||
os.makedirs(directory)
|
||||
except FileNotFoundError:
|
||||
except FileExistsError:
|
||||
# There's a race between os.path.exists() and os.makedirs().
|
||||
# If os.makedirs() fails with FileNotFoundError, the directory
|
||||
# If os.makedirs() fails with FileExistsError, the directory
|
||||
# was created concurrently.
|
||||
pass
|
||||
if not os.path.isdir(directory):
|
||||
|
@ -20,3 +20,7 @@ Bugfixes
|
||||
|
||||
* Fixed a regression where cached foreign keys that use ``to_field`` were
|
||||
incorrectly cleared in ``Model.save()`` (:ticket:`29896`).
|
||||
|
||||
* Fixed a regression in Django 2.0 where ``FileSystemStorage`` crashes with
|
||||
``FileExistsError`` if concurrent saves try to create the same directory
|
||||
(:ticket:`29890`).
|
||||
|
@ -415,9 +415,9 @@ class FileStorageTests(SimpleTestCase):
|
||||
real_makedirs(path)
|
||||
elif path == os.path.join(self.temp_dir, 'raced'):
|
||||
real_makedirs(path)
|
||||
raise FileNotFoundError()
|
||||
elif path == os.path.join(self.temp_dir, 'error'):
|
||||
raise FileExistsError()
|
||||
elif path == os.path.join(self.temp_dir, 'error'):
|
||||
raise PermissionError()
|
||||
else:
|
||||
self.fail('unexpected argument %r' % path)
|
||||
|
||||
@ -432,8 +432,8 @@ class FileStorageTests(SimpleTestCase):
|
||||
with self.storage.open('raced/test.file') as f:
|
||||
self.assertEqual(f.read(), b'saved with race')
|
||||
|
||||
# Exceptions aside from FileNotFoundError are raised.
|
||||
with self.assertRaises(FileExistsError):
|
||||
# Exceptions aside from FileExistsError are raised.
|
||||
with self.assertRaises(PermissionError):
|
||||
self.storage.save('error/test.file', ContentFile('not saved'))
|
||||
finally:
|
||||
os.makedirs = real_makedirs
|
||||
|
Loading…
x
Reference in New Issue
Block a user