[mod_python] session locking causes hang with mpservlets

Graham Dumpleton grahamd at dscpl.com.au
Sun Mar 27 19:31:00 EST 2005

Scott, did you work this out yet?

I had a little play with it, although I had to change your code first  
as what
you posted didn't even work. Needed to use code:

     def respond(self):
         self.req.log_error('Responding ' + self.req.uri)
         self.req.log_error('methodName: '+methodName)
         if methodName == 'index':
             self.req.log_error('Redirecting to login '+prefix+'/login')
         if methodName == 'login':
             self.req.log_error('Doing login')
             self.writeln ('<h1>login_here</h1>')
             return True

This may partly be because I wasn't doing it in document root.

Anyway, after some digging found that adding "self.session.unlock()"  
fix the problem but it has to be in the mpservlets Servlet class. Thus,  
may well be a issue that Daniel (author of mpservlets) may need to look  

The change in mpservlets is:

     def __cleanup_session(self):
         if self.use_session and self.session is not None:
             self.session = None

Ie., add call to unlock() just after saving the session.

Normally this unlock() would be called, but only when the Session object
itself is deleted or by way of a cleanup function registered against the
request using req.register_cleanup().

The problem is that even though one sets self.session to None, this  
mean it will be deleted immediately as one is in part at the mercy of  
Python garbage collector. That it isn't unlocked may actually keep it  
longer and normally it may only be unlocked by request cleanup function
at which point it then gets destroyed.

Unfortunately, because your internal redirect loops back onto the same
servlet, the second time through it tries to lock the same session, but
where the prior hasn't been unlocked yet. Thus deadlock as lock is not
reentrant for same thread.

Thus, believe mpservlet possibly needs to be fixed, but might also  
your design anyway, there possibly being better ways of achieving what  
want. You might want to explain to the list what you are wanting to  
and you might get some helpful suggestions back.


On 27/03/2005, at 8:41 AM, Scott Chapman wrote:

> My previous post didn't address the issue correctly.
> I made some error logging in mpservlets to see where things stop.  In  
> this case, the internal redirect is not being called.  It never gets  
> that far:
> [Sat Mar 26 14:34:02 2005] [error] [client] HANDLER -  
> calling auth
> [Sat Mar 26 14:34:02 2005] [error] [client] HANDLER -  
> calling prep
> [Sat Mar 26 14:34:02 2005] [error] [client] PREP -  
> clearing self.__out
> [Sat Mar 26 14:34:02 2005] [error] [client] PREP -  
> setting self.form
> [Sat Mar 26 14:34:02 2005] [error] [client] PREP -  
> calling __load_vars()
> [Sat Mar 26 14:34:02 2005] [error] [client] PREP -  
> setting self.session
> -- end of log --
> We never see "Redirecting to login" in the log.
> So, the initial establishment of the session is failing, due to  
> locking.
> I have no idea why.
> Scott
> Graham Dumpleton wrote:
>> Try adding:
>>   self.session.unlock()
>> just before the internal redirect and see what happens.
>> I don't believe this should be required as mpservlets is using
>> its own internal redirect which actually saves the session before
>> doing the real internal redirect.
>> Anyway, this "experiment" might at least help you to understand
>> things better.
>> BTW, I am assuming when you say "make session lock=0", you mean
>> setting "use_session" appropriately. Is that correct?
>> Graham
>> On 27/03/2005, at 7:29 AM, Scott Chapman wrote:
>>> Using linux - prefork mpm.
>>> I set my httpd.conf:
>>> StartServers 1
>>> MinSpareServers 1
>>> MaxSpareServers 0
>>> MaxClients 1
>>> MaxRequestsPerChild  0
>>> for this test run.
>>> Here's my UberServlet:
>>> -------------- snip --------------
>>> from mod_python.servlet import Servlet
>>> class uberservlet(Servlet):
>>>     use_session = True
>>>     def respond(self):
>>>         self.req.log_error('Responding')
>>> methodName=self.req.uri[:len(self.req.uri)- 
>>> len(self.req.path_info)][1:]
>>>         self.req.log_error('methodName: '+methodName)
>>>         if methodName == 'index':
>>>             self.req.log_error('Redirecting to login')
>>>             self.internal_redirect('/login')
>>>         if methodName == 'login':
>>>             self.req.log_error('Doing login')
>>>             self.writeln ('<h1>login_here</h1>')
>>>             return True
>>>     def wrapup(self):
>>>         Servlet.wrapup(self)
>>> -------------- snip --------------
>>> When I make Sesssion lock=0, it doesn't hang.
>>> When I don't set lock = 0 (the default) it hangs when trying to  
>>> establish the session:
>>>   self.session = Session.Session(self.req,  
>>> timeout=self.session_timeout)
>>> What problems do I look forward to if I run with lock=0?
>>> Quoting Grisha:
>>> "One thing you may try as an experiment is to disable session locking
>>> (Session(lock=0)). It will still use locking for access to the DBM,  
>>> but it won't lock individual sessions."
>>> Grisha calls this "an experiment".  Can anyone tell me why locking  
>>> is failing and what will happen if I run with locking off?
>>> TIA,
>>> Scott
>>> _______________________________________________
>>> Mod_python mailing list
>>> Mod_python at modpython.org
>>> http://mailman.modpython.org/mailman/listinfo/mod_python

More information about the Mod_python mailing list