Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1579

Show
Ignore:
Timestamp:
12/28/06 17:25:01
Author:
fumanchu
Message:

Fix for #630 (Implicit session locking before_request_body harms uploads). I moved the handling of tools.sessions.locking out of sessions.init and into the Tool. Locking can now be "implicit" (before_handler), "early" (before_request_body), or "explicit" (none).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/_cptools.py

    r1542 r1579  
    179179 
    180180class SessionTool(Tool): 
    181     """Session Tool for CherryPy.""" 
     181    """Session Tool for CherryPy. 
     182     
     183    sessions.locking: 
     184        When 'implicit' (the default), the session will be locked for you, 
     185            just before running the page handler. 
     186        When 'early', the session will be locked before reading the request 
     187            body. This is off by default for safety reasons; for example, 
     188            a large upload would block the session, denying an AJAX 
     189            progress meter (see http://www.cherrypy.org/ticket/630). 
     190        When 'explicit' (or any other value), you need to call 
     191            cherrypy.session.acquire_lock() yourself before using 
     192            session data. 
     193    """ 
     194     
     195    def __init__(self): 
     196        # _sessions.init must be bound after headers are read 
     197        Tool.__init__(self, 'before_request_body', _sessions.init) 
     198     
     199    def _lock_session(self): 
     200        cherrypy._serving.session.acquire_lock() 
    182201     
    183202    def _setup(self): 
     
    187206        method when the tool is "turned on" in config. 
    188207        """ 
    189         Tool._setup(self) 
    190         cherrypy.request.hooks.attach('before_finalize', _sessions.save) 
    191         cherrypy.request.hooks.attach('on_end_request', _sessions.close) 
     208        hooks = cherrypy.request.hooks 
     209         
     210        conf = self._merged_args() 
     211         
     212        p = conf.pop("priority", None) 
     213        if p is None: 
     214            p = getattr(self.callable, "priority", self._priority) 
     215         
     216        hooks.attach(self._point, self.callable, priority=p, **conf) 
     217         
     218        locking = conf.pop('locking', 'early') 
     219        if locking == 'implicit': 
     220            hooks.attach('before_handler', self._lock_session) 
     221        elif locking == 'early': 
     222            # Lock before the request body (but after _sessions.init runs!) 
     223            hooks.attach('before_request_body', self._lock_session, 
     224                         priority=60) 
     225        else: 
     226            # Don't lock 
     227            pass 
     228         
     229        hooks.attach('before_finalize', _sessions.save) 
     230        hooks.attach('on_end_request', _sessions.close) 
    192231 
    193232 
     
    333372_d.staticdir = HandlerTool(static.staticdir) 
    334373_d.staticfile = HandlerTool(static.staticfile) 
    335 # _sessions.init must be bound after headers are read 
    336 _d.sessions = SessionTool('before_request_body', _sessions.init) 
     374_d.sessions = SessionTool() 
    337375_d.xmlrpc = ErrorTool(_xmlrpc.on_error) 
    338376_d.wsgiapp = WSGIAppTool(_wsgiapp.run) 
  • trunk/cherrypy/lib/sessions.py

    r1472 r1579  
    407407 
    408408def init(storage_type='ram', path=None, path_header=None, name='session_id', 
    409          timeout=60, domain=None, secure=False, locking='implicit', 
    410          clean_freq=5, **kwargs): 
     409         timeout=60, domain=None, secure=False, clean_freq=5, **kwargs): 
    411410    """Initialize session object (using cookies). 
    412411     
     
    422421    secure: if False (the default) the cookie 'secure' value will not 
    423422        be set. If True, the cookie 'secure' value will be set (to 1). 
    424     locking: If 'implicit' (the default), this function will lock the 
    425         session for you. If 'explicit' (or any other value), you need 
    426         to call cherrypy.session.acquire_lock() yourself before 
    427         using session data. 
    428423    clean_freq (minutes): the poll rate for expired session cleanup. 
    429424     
     
    456451        if hasattr(sess, "setup"): 
    457452            sess.setup() 
    458      
    459     if locking == 'implicit': 
    460         sess.acquire_lock() 
    461453     
    462454    # Set response cookie 

Hosted by WebFaction

Log in as guest/cpguest to create tickets