#8616: File-based sessions dropped with SESSION_SAVE_EVERY_REQUEST = True
----------------------------------------------+-----------------------------
          Reporter:  [EMAIL PROTECTED]    |         Owner:  jacob              
            Status:  assigned                 |     Milestone:  1.0             
   
         Component:  django.contrib.sessions  |       Version:  SVN             
   
        Resolution:                           |      Keywords:  session, file, 
race
             Stage:  Accepted                 |     Has_patch:  1               
   
        Needs_docs:  0                        |   Needs_tests:  0               
   
Needs_better_patch:  0                        |  
----------------------------------------------+-----------------------------
Comment (by [EMAIL PROTECTED]):

 Sure.  I'll see what I can come up with.  I did some thinking on this last
 night, so I have a head start.

 I've done some more thinking on why unlinking the lock file caused
 problems.  I don't have a deep understanding of low-level I/O or how the
 locking is implemented.  However, my shallow understanding is that there
 are several parts to a file when we have it open:

  - The file descriptor in memory.
  - The file itself.
  - The link to that file in the file system.
  - Perhaps others I am ignorant of...

 I'm not sure where the lock information is actually stored.  The man page
 for flock() says that the lock is on the file, not the file descriptor.
 But what does it mean by "file"?.  The fact that the locking call requires
 a file descriptor and not a file path seems to indicate that the lock
 information is part of the file itself.  If so, I can envision this
 scenario:

  - Request A.load() opens lockfile1, creating it.
  - Request A.load() acquires a shared lock on lockfile1.
  - Request A.load() opens the session file, reads the session data, and
 closes it.
  - Request A.load() closes lockfile1, releasing the lock.
   - Request B.load() opens lockfile1.
   - Request B.load() acquires a shared lock on lockfile1.
  - Request A.load() unlinks lockfile1.  This will succeed on UNIX, but
 probably fail on Windows because the file is in use by Request B.  On
 UNIX, this removes the file system link to lockfile1.  Subsequent attempts
 to open it without creating it will fail.  However, because Request B
 still has an open reference to it, the original file is not yet completely
 gone.
  - Request A.save() opens lockfile2, creating it (because the link to
 lockfile1 has been removed).
  - Request A.save() acquires an exclusive lock on lockfile2 (because the
 shared lock that Request B is holding is on lockfile1, not lockfile2).
  - Request A.save() opens the session file for writing, truncating it.
   - Request B.load() opens the session file, reads the (now empty) session
 data, and closes it.
   - Request B.load() attempts to decode the session data and fails.

 From here on I don't have a good grasp of everything that will happen and
 why the results are so much more severe (at least in my application) than
 the original problem.

 However, if my assumptions are correct, unlinking the lock file can create
 the situation where there are multiple simultaneous locking contexts that
 are unaware of each other, thus defeating the whole purpose of the lock.

 In the end, I would prefer that we not have to do any locking at all.
 I'll try to fix the original problem using os.rename() in the save()
 method.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/8616#comment:25>
Django Code <http://code.djangoproject.com/>
The web framework for perfectionists with deadlines
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to