[mod_python] The right way to handle sessions

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()".


More information about the Mod_python mailing list