|
Byron Ellacott
bje at apnic.net
Fri Aug 13 10:17:07 EDT 2004
Amir Salihefendic wrote:
> I welcome myself to this list ;-)
Welcome!
[working example]
> def createSession(req):
> def getSameSession(req):
The important thing to note here is that the code is identical in both
calls. That is, if you call Session.Session(req) with no session ID in
cookies, or the existing session ID has no matching session stored on
disk, a new session ID is generated.
But, the session is /not/ written to disk.
> def createSession(req):
> return getSameSession(req)
> def getSameSession(req):
> return same_session.id()
So when you change to calling getSameSession() from createSession() you
are in fact creating /two/ sessions. My guess would be that your
apparent infinite loop is in fact a deadlock, caused by the fact that
your second created session will be reusing the session ID created by
the first one, and then attempting to establish a global lock on that
session ID. Bad.
> This does not work - it makes an infinitive loop..! Now to fix this you
> need to unlock the session in createSession (.. I have no clue why you
> have to do this..?). And then you need to restart apache... i.e.:
This bears up my analysis well. The locking done by the Session module
is an Apache-wide lock on the session ID. So, when createSession()
first creates a session, it locks that sid. Then, it calls
getSameSession() which attempts to lock the same sid. The lock call
blocks here, waiting for the first lock to be released, but that release
will never come. If you cause the first created session to unlock
itself, you will not create a deadlock, but you will need to restart
apache to break an existing deadlock.
> But this does not work quite well.. If you delete the Session:
> And then you do this:
> First time the id's aren't same - after that they are the same.
When a session has been deleted, it is marked as invalid and calling
.load() on that sid will fail. .__init__() will create a new sid if
.load() fails for an existing one, so I suspect you are seeing this
behaviour.
Overall, it seems you are making the session management process far more
complicated than it needs to be. Under what circumstances do you call
createSession() instead of getSameSession() ?
I am successfully using the Session module to handle an HTML forms based
login system:
session = Session.Session(req)
if NeedAuth and not session.has_key('username'):
redirect(AuthPage)
ServePage(req)
session.save()
return apache.OK
This is a simplification, since I use an extensible application object
that allows you to change how sessions are generated and how users are
authenticated, but it boils down to the above. I create a new session
or get an existing session. I do not care which. If the page being
requested needs auth, but the session doesn't contain a username key, I
redirect[1] to the login page, which stores the username value into the
session if the user presents the right credentials. Otherwise, I serve
the requested page, then save the session, and Bob's a builder.
Note that I cannot distinguish between an expired session and no session
at all, but this is a limitation of the Session module. I can
distinguish between a new session and an existing session by calling
session.is_new(), but that distinction turns out not to be very important.
At some point, I will need to extract the sid from the cookie set
myself, to be able to distinguish between a timed out session, an
invalidated session, a missing session and a brand new session. (Or
else I'll have to patch the Session module, which I'm not real keen to do.)
--
bje
[1] The 'redirects' I do are simply changing what view my code believes
it is processing, so execution continues down the line, and
session.save() is called in due order. If you're using an Apache
internal redirect or a 302/303 redirect, you should ensure new sessions
are saved as soon as created with "if session.is_new(): session.save()".
|