quetz-mod_python-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jim Gallacher <jg.li...@sympatico.ca>
Subject Re: [mod_python] Sessions performance and some numbers
Date Sat, 09 Apr 2005 14:25:44 GMT
Nicolas Lehuen wrote:
> On Apr 9, 2005 3:00 AM, Jim Gallacher <jg.lists@sympatico.ca> wrote:
> 
>>Gregory (Grisha) Trubetskoy wrote:
>>
>>>[also moved this to python-dev]
>>>
>>>
>>>On Fri, 8 Apr 2005, Nicolas Lehuen wrote:
>>>
>>>
>>>>Well, I had a go last night, but my brain was a little fuzzy too, so I
>>>>don't mind a double-check. I didn't use the global lock n° 0, which
>>>>would serialize all access to all sessions, but a lock named after the
>>>>session, just like it was done in BaseSession.lock() and
>>>>BaseSession.unlock().
>>>>
>>>>BTW, I'm not sure I understand the current locking system in
>>>>BaseSession : it looks to me as if the lock on the session was held
>>>>for the duration of the whole request (the lock being released during
>>>>the request cleanup). Grisha, is this true ? If this is so, then there
>>>>is no need to lock anything in FileSession, as the BaseSession already
>>>>ensure a proper level of locking.
>>>
>>>
>>>Yes, there is a lock for the duration of the session. This is to make
>>>sure that no two requests for the same session are processed at the same
>>>time (this is a little documented artifact of sessions in other
>>>environments, e.g. jsp).
>>>
>>>The lock 0 is there to serialize access to the DBM. So we have "session
>>>locks" and "dbm store lock" which serve different purposes.
>>>
>>>Since there is a one-to-one correspondence between sessions and files in
>>>a FileSession, you're right the lock 0 use is probably not appropriate
>>>(although disk I/O is ultimately serialized by the OS).
>>>
>>>However, keep in mind that BaseSession (session locks) is optional (it's
>>>an __init__ argument), so when session locking is off, you still (and
>>>especially more so!) need a store lock.
>>>
>>>So I guess the bottom line is that FileSession locking is going to be a
>>>little different :-)
>>>
>>>Grisha
>>
>>Sorry for the long post here - just kind of thinking out loud.
>>
>>I've been playing with the code Nicolas committed and found the file
>>locking is not working quite right. I couldn't figure out what was going
>>wrong until I re-read Grisha's comments.
>>
>>There is a deadlock when accessing an existing session with session
>>locking on. A DOS results for that session, and in the worst case a
>>complete DOS for any connections. The following bash script demonstrates
>>the effect:
>>
>>#!/bin/sh
>>ab -n 1 http://localhost/session_test.py
>>ab -n 1 -C pysid=723b98c0abf885a97b8bdc8d806b4bd8 \
>>    http://localhost/session_test.py
>>
>>where pysid is a valid session id.
>>
>>The first call to the url will succeed, while the second one will fail
>>with ab timing out. Here is the FileSession program flow as I see it:
>>
>>sess = FileSession.FileSession.__init__(req,lock=1)
>>   - calls BaseSession.__init__(req,lock=1)
>>
>>BaseSession.__init__()
>>   - gets the existing session id from the request cookie
>>   - acquires a lock for this session
>>   - registers the unlock_session_cleanup
>>   - calls BaseSession.load()
>>
>>BaseSession.load()
>>   - calls self.do_load() which is overriden in FileSession
>>
>>FileSession.do_load()
>>   - attempts to acquire a lock on the session, but is blocked since
>>session was previously locked in BaseSession.__init__()
>>   - client times out
>>   - unlock_session_cleanup is never run so lock is never released
>>   - this apache thread or child is deadlocked
>>   - access to this session is blocked forever
>>
>>Call the url enough times for an exisiting session, and apache will
>>reach MaxClients and refuse additional connections. DOS. oops.
>>
>>I assume that overriding BaseSession.load() is the best way to change
>>the locking behaviour and fix the problem. I haven't worked out the
>>implications of that yet - I guess I need a little more head scratching
>>time.
>>
>>On another note, I also wonder if this type of locking problem might
>>also be a factor in http://issues.apache.org/jira/browse/MODPYTHON-31
>>
>>Regards,
>>Jim
>>
>>
> 
> 
> Given the fact that getting the session object holds a lock for the
> whole duration of the request (from the session instantiation to the
> request cleanup), the locking code I've wrote in FileSession.do_load
> is redundant. What I don't understand, though, is why I didn't see any
> deadlock when I tested the code, whereas you see one. I assumed that
> the APR locking facility was reentrant, but maybe it's not. Or maybe
> it's reentrant on Win32 with threads, and not in an over environment.

On further consideration, maybe I'm using the term deadlock incorrectly 
here. There are not 2 processes trying to acquire the lock, rather one 
process trying to acquire the same lock twice, once for the session and 
once for the file access. The second attempt blocks forever so the 
request can't complete and the lock for that session is never released. 
Subsequent requests for that session should fail, since the lock is 
still held by that first, blocked request. And I don't understand why 
it's not a problem in the threaded model as it seems to be in the 
prefork model.

> Anyway... let's get rid of this redundant locking code in FileSession
> and the problem will be solved. The only problem, as Grisha pointed
> out, is that locking is an optional feature, you can disable it by
> passing lock=0 in the session constructor call. If locking is
> disabled, there is a potential for trouble in FileSession. For now,
> I'll just say that if you want to disable locking, then you know what
> you are doing...

Explicit is better than implicit and I don't like suprises. So maybe use 
2 different locks?
Session lock:
         _apache._global_lock(self._req.server, self._sid)
File lock:
         _apache._global_lock(self._req.server, 'file_%s' % self._sid)

> As for MODPYTHON-31, as Graham noted in the comments, it looks like a
> problem in the reporter's configuration file. I've closed the bug
> report.

I didn't look at it really closely, but saw some similarities - a 
request acquires a session lock but goes into an infinite loop and so 
never releases the lock. I assume the browser will eventually time out 
and drop the connection. How does apache handle this internally? Does 
the registered cleanup code still get a chance to run and release any 
locks?

Regards,
Jim

Mime
View raw message