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

Ticket #680 (defect)

Opened 2 years ago

Last modified 1 year ago

sessions save() and close() assume init() was called

Status: closed (fixed)

Reported by: guest Assigned to: rdelon
Priority: normal Milestone: 3.1
Component: CherryPy code Keywords: session
Cc:

(I just started using CherryPy yesterday, so take this with a grain of salt)

If an exception (eg. HTTPError) is raised before sessions.init() is called, an exception will be raised when either sessions.save() or sessions.close() try to access cherrypy.session.

Example using http_methods_allowed() from http://tools.cherrypy.org/wiki/HTTPMethodFiltering:

  1. [on_start_resource] http_methods_allowed() decides the HTTP method is not allowed and raises a HTTPError.
  2. Note that [before_request_body] never happens and sessions.init() is not called.
  3. [before_finalize] sessions.save() is called and raises an exception when trying to access cherrypy.session. Boom!

Here is a patch against lib/sessions.py to make sure sessions.init() was called before accessing cherrypy.session:

--- sessions.py.orig    2007-03-30 10:59:59.000000000 +0100
+++ sessions.py 2007-03-30 11:40:01.000000000 +0100
@@ -395,6 +395,9 @@
 
 def save():
     """Save any changed session data."""
+    # If an exception was raised, init may not have been called
+    if not hasattr(cherrypy.request, "_session_init_flag"):
+        return
     # Guard against running twice
     if hasattr(cherrypy.request, "_sessionsaved"):
         return
@@ -414,10 +417,12 @@
 
 def close():
     """Close the session object for this request."""
-    sess = cherrypy.session
-    if sess.locked:
-        # If the session is still locked we release the lock
-        sess.release_lock()
+    # If an exception was raised, init may not have been called
+    if hasattr(cherrypy.request, "_session_init_flag"):
+        sess = cherrypy.session
+        if sess.locked:
+            # If the session is still locked we release the lock
+            sess.release_lock()
 close.failsafe = True
 close.priority = 90
 
@@ -446,7 +451,8 @@
     
     request = cherrypy.request
     
-    # Guard against running twice
+    # Guard against running twice and signal save and close not
+    # to run if init was never called
     if hasattr(request, "_session_init_flag"):
         return
     request._session_init_flag = True

Attachments

cherrypy_session.patch (0.9 kB) - added by guest on 04/02/07 05:53:33.

Change History

04/01/07 19:20:59: Modified by fumanchu

I'm of mixed opinion on this: the reasoning given is fine, but part of me wants it to break so that "legitimate errors" don't pass silently.

04/02/07 05:53:33: Modified by guest

  • attachment cherrypy_session.patch added.

04/02/07 05:54:28: Modified by guest

Ah, I did not think of the genuine error, calling save() or close() without a prior call to init().

Here is an alternative solution which fixes the issue while preserving the error:

Do not hook save() and close() calls unconditionally in SessionTool._setup(). Instead, hook them in sessions.init(). So save() and close() are called iff init() was called. A call to those functions without a prior call to init() will continue raising an exception.

I hope this solution makes sense, see patch.

04/02/07 05:56:23: Modified by guest

To clarify: please ignore the original inline text patch and consider the attached patch file instead.

06/17/07 18:57:46: Modified by fumanchu

  • status changed from new to closed.
  • resolution set to fixed.
  • milestone set to 3.1.

Fixed in [1673]. I went for a more data-driven approach, testing for hasattr(cherrypy, "session") instead of delaying the hooking. This should allow people to use the functions in sessions.py more easily even if they're not using the SessionTool?. It's important to keep Tool code separate from library code where possible.

08/22/07 12:10:49: Modified by fumanchu

Actual, working fix (and test!) in [1707]. ;)

Hosted by WebFaction

Log in as guest/cpguest to create tickets