Fixed #29890 -- Fixed FileSystemStorage crash if concurrent saves try to create the same directory.

Regression in 632c4ffd9c.
This commit is contained in:
Tim Graham 2018-10-31 19:25:53 -04:00
parent 3d4d0a25b2
commit 98ef3829e9
3 changed files with 10 additions and 6 deletions

View File

@ -240,9 +240,9 @@ class FileSystemStorage(Storage):
os.umask(old_umask) os.umask(old_umask)
else: else:
os.makedirs(directory) os.makedirs(directory)
except FileNotFoundError: except FileExistsError:
# There's a race between os.path.exists() and os.makedirs(). # 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. # was created concurrently.
pass pass
if not os.path.isdir(directory): if not os.path.isdir(directory):

View File

@ -20,3 +20,7 @@ Bugfixes
* Fixed a regression where cached foreign keys that use ``to_field`` were * Fixed a regression where cached foreign keys that use ``to_field`` were
incorrectly cleared in ``Model.save()`` (:ticket:`29896`). 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`).

View File

@ -415,9 +415,9 @@ class FileStorageTests(SimpleTestCase):
real_makedirs(path) real_makedirs(path)
elif path == os.path.join(self.temp_dir, 'raced'): elif path == os.path.join(self.temp_dir, 'raced'):
real_makedirs(path) real_makedirs(path)
raise FileNotFoundError()
elif path == os.path.join(self.temp_dir, 'error'):
raise FileExistsError() raise FileExistsError()
elif path == os.path.join(self.temp_dir, 'error'):
raise PermissionError()
else: else:
self.fail('unexpected argument %r' % path) self.fail('unexpected argument %r' % path)
@ -432,8 +432,8 @@ class FileStorageTests(SimpleTestCase):
with self.storage.open('raced/test.file') as f: with self.storage.open('raced/test.file') as f:
self.assertEqual(f.read(), b'saved with race') self.assertEqual(f.read(), b'saved with race')
# Exceptions aside from FileNotFoundError are raised. # Exceptions aside from FileExistsError are raised.
with self.assertRaises(FileExistsError): with self.assertRaises(PermissionError):
self.storage.save('error/test.file', ContentFile('not saved')) self.storage.save('error/test.file', ContentFile('not saved'))
finally: finally:
os.makedirs = real_makedirs os.makedirs = real_makedirs