summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-08-02 08:45:20 -0400
committerChris McDonough <chrism@plope.com>2011-08-02 08:45:20 -0400
commit6456c2d69727369826b3cc31e168704a402bab89 (patch)
tree04702faa812ed7a849c9d1d5ba7d4fce95332c2d
parent95a3791409f4a936c47e7018e75f14fc3b701380 (diff)
downloadpyramid-6456c2d69727369826b3cc31e168704a402bab89.tar.gz
pyramid-6456c2d69727369826b3cc31e168704a402bab89.tar.bz2
pyramid-6456c2d69727369826b3cc31e168704a402bab89.zip
avoid memory leak potential when assigning sys.exc_info() result to an attr of the request
-rw-r--r--pyramid/router.py9
-rw-r--r--pyramid/tests/test_router.py13
2 files changed, 16 insertions, 6 deletions
diff --git a/pyramid/router.py b/pyramid/router.py
index aa9e4a1ba..ddec23cdb 100644
--- a/pyramid/router.py
+++ b/pyramid/router.py
@@ -168,7 +168,6 @@ class Router(object):
# handle exceptions raised during root finding and view-exec
except Exception, why:
- exc_info = sys.exc_info()
# clear old generated request.response, if any; it may
# have been mutated by the view, and its state is not
# sane (e.g. caching headers)
@@ -176,7 +175,7 @@ class Router(object):
del attrs['response']
attrs['exception'] = why
- attrs['exc_info'] = exc_info
+ attrs['exc_info'] = sys.exc_info()
for_ = (IExceptionViewClassifier,
request_iface.combined,
@@ -217,8 +216,10 @@ class Router(object):
request.registry = registry
response = self.handle_request(request)
finally:
- if request is not None and request.finished_callbacks:
- request._process_finished_callbacks()
+ if request is not None:
+ if request.finished_callbacks:
+ request._process_finished_callbacks()
+ request.exc_info = None # avoid leak
return response(request.environ, start_response)
finally:
diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py
index e44465992..b943f1ee6 100644
--- a/pyramid/tests/test_router.py
+++ b/pyramid/tests/test_router.py
@@ -790,6 +790,7 @@ class TestRouter(unittest.TestCase):
from pyramid.interfaces import IRequest
from pyramid.interfaces import IViewClassifier
from pyramid.interfaces import IRequestFactory
+ from pyramid.interfaces import IExceptionViewClassifier
def rfactory(environ):
return request
self.registry.registerUtility(rfactory, IRequestFactory)
@@ -799,16 +800,24 @@ class TestRouter(unittest.TestCase):
directlyProvides(context, IContext)
self._registerTraverserFactory(context, subpath=[''])
response = DummyResponse()
+ response.app_iter = ['OK']
view = DummyView(response, raise_exception=RuntimeError)
environ = self._makeEnviron()
+ def exception_view(context, request):
+ self.assertEqual(request.exc_info[0], RuntimeError)
+ return response
self._registerView(view, '', IViewClassifier, IRequest, IContext)
+ self._registerView(exception_view, '', IExceptionViewClassifier,
+ IRequest, RuntimeError)
router = self._makeOne()
start_response = DummyStartResponse()
- self.assertRaises(RuntimeError, router, environ, start_response)
+ result = router(environ, start_response)
+ self.assertEqual(result, ['OK'])
# ``exception`` must be attached to request even if a suitable
# exception view cannot be found
self.assertEqual(request.exception.__class__, RuntimeError)
- self.assertEqual(request.exc_info[0], RuntimeError)
+ # we clean up the exc_info after the request
+ self.assertEqual(request.exc_info, None)
def test_call_view_raises_exception_view(self):
from pyramid.interfaces import IViewClassifier