Django

Code

Ticket #7683 (closed: fixed)

Opened 5 months ago

Last modified 4 months ago

Streaming Upload file deleted before move

Reported by: emperorcezar Assigned to: nobody
Milestone: 1.0 beta Component: Core framework
Version: SVN Keywords: 2070-fix
Cc: emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de, django@statesofpop.de, dcwatson@gmail.com, donspauldingii@gmail.com Triage Stage: Ready for checkin
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

In /django/db/models/base.py on line 532 it's calling raw_field.close() before it tries moving the file and that's causing the following traceback.

raw_field.close() is deleting the temp file before it gets a chance to be moved.

Environment:

Request Method: POST
Request URL: http://localhost:8000/essayupload/
Django Version: 0.97-pre-SVN-7870
Python Version: 2.5.2
Installed Applications:
['appid.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'appid.apply',
 'django.contrib.admin',
 'registration',
 'extensions']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'appid.auth.middleware.AuthenticationMiddleware',
 'django.middleware.doc.XViewMiddleware',
 'django.middleware.locale.LocaleMiddleware')


Traceback:
File "/usr/lib/python2.5/site-packages/django/core/handlers/base.py" in get_response
  86.                 response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.5/site-packages/django/contrib/auth/decorators.py" in __call__
  67.             return self.view_func(request, *args, **kwargs)
File "/home/cezar/code/appid/apply/views.py" in essayUpload
  316.             object = form.save(commit=False)
File "/usr/lib/python2.5/site-packages/django/newforms/models.py" in save
  273.         return save_instance(self, self.instance, self._meta.fields, fail_message, commit)
File "/usr/lib/python2.5/site-packages/django/newforms/models.py" in save_instance
  44.         f.save_form_data(instance, cleaned_data[f.name])
File "/usr/lib/python2.5/site-packages/django/db/models/fields/__init__.py" in save_form_data
  865.             getattr(instance, "save_%s_file" % self.name)(data.name, data, save=False)
File "/usr/lib/python2.5/site-packages/django/db/models/fields/__init__.py" in <lambda>
  817.         setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_field, save=True: instance._save_FIELD_file(self, filename, raw_field, save))
File "/usr/lib/python2.5/site-packages/django/db/models/base.py" in _save_FIELD_file
  533.             file_move_safe(raw_field.temporary_file_path(), full_filename)
File "/usr/lib/python2.5/site-packages/django/core/files/move.py" in file_move_safe
  40.         file_move(old_file_name, new_file_name)
File "/usr/lib/python2.5/shutil.py" in move
  199.             copy2(src,dst)
File "/usr/lib/python2.5/shutil.py" in copy2
  91.     copyfile(src, dst)
File "/usr/lib/python2.5/shutil.py" in copyfile
  46.         fsrc = open(src, 'rb')

Exception Type: IOError at /essayupload/
Exception Value: [Errno 2] No such file or directory: u'02-heaven_on_their_minds_192_ogg_cbr_ex.ogg'

Attachments

7683.diff (0.7 kB) - added by gorman on 07/14/08 19:13:46.
Patch for #7683
7683.2.diff (0.7 kB) - added by andrewsk on 07/15/08 04:48:30.
Close method on the NamedTemporaryFile? removes temporary file before it can be moved somewhere.
7683.3.diff (1.8 kB) - added by screeley on 07/22/08 10:16:03.
I think the close should still be called to handle self._file.file.close() as well as setting self._file.close_called. raw_field.close() should be moved after the file_move_safe and the exception should be caught within the close. Tested on Linux.
7683.4.diff (1.8 kB) - added by screeley on 07/26/08 19:37:40.
Catches the specific OSError and passes the rest.
7683.5.diff (1.9 kB) - added by spaetz on 07/28/08 02:39:02.
same as patch 7683.3, but just catching errno ==2 (missing file)

Change History

(follow-up: ↓ 2 ) 07/08/08 21:08:09 changed by axiak

  • status changed from new to closed.
  • needs_better_patch changed.
  • resolution set to duplicate.
  • needs_tests changed.
  • needs_docs changed.

This is actually not the problem. The problem is #7675.

(in reply to: ↑ 1 ) 07/09/08 10:15:58 changed by emperorcezar

  • status changed from closed to reopened.
  • resolution deleted.

Replying to axiak:

This is actually not the problem. The problem is #7675.

I applied the patch from #7675. Now getting the following traceback.

Environment:

Request Method: POST
Request URL: http://localhost:8000/essayupload/
Django Version: 0.97-pre-SVN-7871
Python Version: 2.5.2
Installed Applications:
['appid.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'appid.apply',
 'django.contrib.admin',
 'registration',
 'extensions']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'appid.auth.middleware.AuthenticationMiddleware',
 'django.middleware.doc.XViewMiddleware',
 'django.middleware.locale.LocaleMiddleware')


Traceback:
File "/usr/lib/python2.5/site-packages/django/core/handlers/base.py" in get_response
  86.                 response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.5/site-packages/django/contrib/auth/decorators.py" in __call__
  67.             return self.view_func(request, *args, **kwargs)
File "/home/cezar/code/appid/apply/views.py" in essayUpload
  316.             object = form.save(commit=False)
File "/usr/lib/python2.5/site-packages/django/newforms/models.py" in save
  273.         return save_instance(self, self.instance, self._meta.fields, fail_message, commit)
File "/usr/lib/python2.5/site-packages/django/newforms/models.py" in save_instance
  44.         f.save_form_data(instance, cleaned_data[f.name])
File "/usr/lib/python2.5/site-packages/django/db/models/fields/__init__.py" in save_form_data
  865.             getattr(instance, "save_%s_file" % self.name)(data.name, data, save=False)
File "/usr/lib/python2.5/site-packages/django/db/models/fields/__init__.py" in <lambda>
  817.         setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_field, save=True: instance._save_FIELD_file(self, filename, raw_field, save))
File "/usr/lib/python2.5/site-packages/django/db/models/base.py" in _save_FIELD_file
  533.             raw_field.close()
File "/usr/lib/python2.5/site-packages/django/core/files/uploadedfile.py" in close
  204.     def close(self):                return self._file.close()
File "/usr/lib/python2.5/tempfile.py" in close
  411.                 self.unlink(self.name)

Exception Type: OSError at /essayupload/
Exception Value: [Errno 2] No such file or directory: '/tmp/tmpVwM5Fd.upload'

07/09/08 15:20:46 changed by emperorcezar

  • cc set to emperorcezar@gmail.com.

07/14/08 19:13:46 changed by gorman

  • attachment 7683.diff added.

Patch for #7683

07/14/08 19:16:25 changed by gorman

  • status changed from reopened to closed.
  • resolution set to fixed.
  • has_patch set to 1.
  • component changed from Uncategorized to Core framework.

Added a patch.

07/14/08 19:20:19 changed by mtredinnick

  • status changed from closed to reopened.
  • resolution deleted.

07/15/08 01:47:29 changed by andrewsk

  • cc changed from emperorcezar@gmail.com to emperorcezar@gmail.com, prigun@gmail.com.

Attached patch doesn't fix the problem either. It looks like raw_field.close() tries to delete the file, and if file was moved first, it throws an exception. I'm wondering if we need to call close for NamedTemporaryFile? objects at all? Original patch 2070 didn't override this method and everything worked.

07/15/08 04:48:30 changed by andrewsk

  • attachment 7683.2.diff added.

Close method on the NamedTemporaryFile? removes temporary file before it can be moved somewhere.

07/15/08 05:21:46 changed by ramiro

  • keywords set to 2070-fix.

See also #7658

07/15/08 17:38:36 changed by Karen Tracey <kmtracey@gmail.com>

#7766 reported close before move as a problem also.

07/22/08 10:16:03 changed by screeley

  • attachment 7683.3.diff added.

I think the close should still be called to handle self._file.file.close() as well as setting self._file.close_called. raw_field.close() should be moved after the file_move_safe and the exception should be caught within the close. Tested on Linux.

07/22/08 10:17:09 changed by screeley

  • cc changed from emperorcezar@gmail.com, prigun@gmail.com to emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com.

07/24/08 08:27:48 changed by chr

7683.3.dif works on mac osx 10.5, apache2 modwsgi

07/25/08 06:11:06 changed by mafix

7683.3.diff works on ubuntu linux - hardy - apache2 mod-wsgi

some one shut apply it to the subversion..

thanks for the patch

07/25/08 09:46:16 changed by osm@sspaeth.de

  • cc changed from emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com to emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de.

patch .3.diff works like a charm. CC'ing myself

07/25/08 16:52:27 changed by chr

  • cc changed from emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de to emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de, django@statesofpop.de.

07/26/08 05:25:40 changed by masneyb@gftp.org

This patch works correctly for me under Debian/Lenny.

07/26/08 17:33:58 changed by mtredinnick

  • needs_better_patch set to 1.
  • stage changed from Unreviewed to Accepted.

On the grounds that bare except catching is bad, the change to the close() method should try to catch as specific an exception as possible (and possibly even check the errno value).

Handling a specific error is good. Accidentally disguising all errors as if they are okay is bad.

07/26/08 19:37:40 changed by screeley

  • attachment 7683.4.diff added.

Catches the specific OSError and passes the rest.

07/28/08 02:39:02 changed by spaetz

  • attachment 7683.5.diff added.

same as patch 7683.3, but just catching errno ==2 (missing file)

(follow-ups: ↓ 17 ↓ 21 ) 07/28/08 02:41:21 changed by spaetz

Depending on how specific you prefer to catch the error, patch 7683.5 will just catch OSError with errno==2 (missing file) and pass on all other exceptions. Pick you choice (I think just catching all OSError as patch 7683.4 did should be fine).

(in reply to: ↑ 16 ) 07/28/08 02:48:59 changed by spaetz

Replying to spaetz:

patch 7683.5 will just catch OSError with errno==2 (missing file)

Bear with my spamming. patch 7683.5 is based on 7683.4 and not on 7683.3 as accidentally written in the description.

07/28/08 12:07:19 changed by mtredinnick

  • stage changed from Accepted to Ready for checkin.

Catching errno=2 is the right thing here, so thanks for the final patch. There are plenty of other filesystem errors that could occur that are unrelated and serious enough to want to know about.

Whoever checks this in should give it another read over for sanity, but this should be pretty much ready now.

07/29/08 15:14:49 changed by anonymous

  • cc changed from emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de, django@statesofpop.de to emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de, django@statesofpop.de, dcwatson@gmail.com.

07/29/08 17:42:39 changed by Karen Tracey <kmtracey@gmail.com>

#8021 is another report of this, I believe.

(in reply to: ↑ 16 ) 07/30/08 20:34:13 changed by anonymous

  • milestone set to 1.0 beta.

Replying to spaetz:

Depending on how specific you prefer to catch the error, patch 7683.5 will just catch OSError with errno==2 (missing file) and pass on all other exceptions. Pick you choice (I think just catching all OSError as patch 7683.4 did should be fine).

It's good work in ubuntu 8.04 and django 1.0a(#8156)

08/01/08 15:00:09 changed by donspaulding

  • cc changed from emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de, django@statesofpop.de, dcwatson@gmail.com to emperorcezar@gmail.com, prigun@gmail.com, screeley@optaros.com, sebastian@sspaeth.de, django@statesofpop.de, dcwatson@gmail.com, donspauldingii@gmail.com.

Does this patch still need improvement?

08/04/08 00:41:34 changed by spaetz

I don't think so. If you agree, please reset the "patch needs improvement" flag. Please note mtredinnick: "Whoever checks this in should give it another read over for sanity, but this should be pretty much ready now."

08/04/08 00:45:46 changed by Alex

  • needs_better_patch deleted.

08/05/08 12:43:06 changed by jacob

  • status changed from reopened to closed.
  • resolution set to fixed.

(In [8217]) Fixed #7683: Try not to delete uploaded files before moving them, and don't wig out of someone else does. Patch from screeley and spaetz.


Add/Change #7683 (Streaming Upload file deleted before move)




Change Properties
Action