#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
-~----------~----~----~----~------~----~------~--~---