Issue #309 resolved

CP encourages confusion between threads and requests

Robert Brewer
created an issue

The {{{cherrypy.request}}}, {{{.response}}}, and even {{{.threadData}}} attributes are all implemented as threading.local objects. This results in a simple interface for users: import cherrypy, access attributes of those three objects, and you should be relatively safe from sharing data with concurrent, competing threads. Unfortunately, it's not enough to be safe from concurrent, competing threads. We really wish to be isolated from competing ''requests'', and those whether concurrent or not.

Under the current implementation (2.1 RC1), threads are often reused, and attributes which are added during one request must be carefully removed before the next request which uses the same thread. This is difficult enough when you know what attributes have been added; however, the core cannot know what attributes users may add to {{{threadData}}}, for example. It's possible to ameliorate this a bit by using few core attributes, and recommending that users stick ''all'' of their application-specific data into a single {{{cherrypy.threadData.mydata}}} dict (and then using a custom filter to clear that dict). But that's a lot to expect.

A more robust solution might be to use a single threadlocal object, {{{cherrypy.serving}}}, and make the request, response, and userdata objects be attributes of it. Each request, response, and userdata object would be created fresh at the start of each server.request(); once the conversation has been completed, then they could be del'ed in one line of code. [The definition of "completed conversation" has its own problems, but I think we can control those.]

Comments (2)

  1. Robert Brewer reporter

    Fixed in [665]. threadData was not moved, and remains a threading.local() object. cherrypy.request and .response are now proxies to cherrypy.serving.request and .response, and get replaced with fresh objects at the start of each HTTP request. All of the builtin filters that stuck data into threadData now stick that data into cherrypy.request instead, since they all seemed to be request data, not thread data. Some user code may break if it expected builtin data to be present in threadData.

    If ticket #311 gets implemented in the future, it might be good to del the request and response objects immediately after all the afterResponseWritten methods have run.

    Also at some point in the future, it might be good to make cherrypy.serving.request be an instance of _cphttptools.Request instead of the dummy _AttributeDump class. The .response could become a new _cphttptools.Response object, as well. It might make the code cleaner.

  2. Log in to comment