Ticket #16108: django-file-storage-remove-race.patch
File django-file-storage-remove-race.patch, 3.9 KB (added by , 13 years ago) |
---|
-
tests/regressiontests/file_storage/tests.py
304 304 """ 305 305 File storage should be robust against directory creation race conditions. 306 306 """ 307 real_makedirs = os.makedirs 308 307 309 # Monkey-patch os.makedirs, to simulate a normal call, a raced call, 308 310 # and an error. 309 311 def fake_makedirs(path): 310 312 if path == os.path.join(self.temp_dir, 'normal'): 311 os.mkdir(path)313 real_makedirs(path) 312 314 elif path == os.path.join(self.temp_dir, 'raced'): 313 os.mkdir(path)315 real_makedirs(path) 314 316 raise OSError(errno.EEXIST, 'simulated EEXIST') 315 317 elif path == os.path.join(self.temp_dir, 'error'): 316 318 raise OSError(errno.EACCES, 'simulated EACCES') 317 319 else: 318 320 self.fail('unexpected argument %r' % path) 319 321 320 real_makedirs = os.makedirs321 322 try: 322 323 os.makedirs = fake_makedirs 323 324 … … 333 334 334 335 # Check that OSErrors aside from EEXIST are still raised. 335 336 self.assertRaises(OSError, 336 lambda: self.storage.save('error/test.file', 337 ContentFile('not saved'))) 337 self.storage.save, 'error/test.file', ContentFile('not saved')) 338 338 finally: 339 339 os.makedirs = real_makedirs 340 340 341 def test_remove_race_handling(self): 342 """ 343 File storage should be robust against file removal race conditions. 344 """ 345 real_remove = os.remove 346 347 # Monkey-patch os.remove, to simulate a normal call, a raced call, 348 # and an error. 349 def fake_remove(path): 350 if path == os.path.join(self.temp_dir, 'normal.file'): 351 real_remove(path) 352 elif path == os.path.join(self.temp_dir, 'raced.file'): 353 real_remove(path) 354 raise OSError(errno.ENOENT, 'simulated ENOENT') 355 elif path == os.path.join(self.temp_dir, 'error.file'): 356 raise OSError(errno.EACCES, 'simulated EACCES') 357 else: 358 self.fail('unexpected argument %r' % path) 359 360 try: 361 os.remove = fake_remove 362 363 self.storage.save('normal.file', ContentFile('delete normally')) 364 self.storage.delete('normal.file') 365 self.assertFalse(self.storage.exists('normal.file')) 366 367 self.storage.save('raced.file', ContentFile('delete with race')) 368 self.storage.delete('raced.file') 369 self.assertFalse(self.storage.exists('normal.file')) 370 371 # Check that OSErrors aside from ENOENT are still raised. 372 self.storage.save('error.file', ContentFile('delete with error')) 373 self.assertRaises(OSError, self.storage.delete, 'error.file') 374 finally: 375 os.remove = real_remove 376 377 341 378 class CustomStorage(FileSystemStorage): 342 379 def get_available_name(self, name): 343 380 """ -
django/core/files/storage.py
219 219 def delete(self, name): 220 220 name = self.path(name) 221 221 # If the file exists, delete it from the filesystem. 222 # Note that there is a race between os.path.exists and os.remove: 223 # if os.remove fails with ENOENT, the file was removed 224 # concurrently, and we can continue normally. 222 225 if os.path.exists(name): 223 os.remove(name) 226 try: 227 os.remove(name) 228 except OSError, e: 229 if e.errno != errno.ENOENT: 230 raise 224 231 225 232 def exists(self, name): 226 233 return os.path.exists(self.path(name))