Pylons/pyramid — Issue #454: Exception is not set on request passed to a finished callback
Author: rspivak
Created: 2012-03-02 07:29:23+00:00
State: open

Tested with Pyramid master branch.

Here is a simple code to demonstrate the problem:

```python
from waitress import serve
from pyramid.config import Configurator
from pyramid.events import NewRequest

def mysubscriber(event):
event.request.add_finished_callback(callback)

def callback(request):
"""Finished callback"""
if request.exception is not None:
print '***********************'
print '* EXCEPTION DETECTED! *'
print '***********************'
else:
print '***********************'
print '* NO EXCEPTION :( *'
print '***********************'

def hello(request):
raise Exception('Check me in finished callback!')

if __name__ == '__main__':
config = Configurator()
config.add_route('home', '/')
config.add_view(hello, route_name='home')
config.add_subscriber(mysubscriber, NewRequest)

serve(config.make_wsgi_app(), host='', port=6543)
```

Here is an output when trying to access '/'.
Instead of EXCEPTION DETECTED! we get NO EXCEPTION :(

$ python testcallback.py
serving on http://0.0.0.0:6543
***********************
* NO EXCEPTION :( *
***********************
ERROR:waitress:Exception when serving /
Traceback (most recent call last):
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/channel.py", line 329, in service
task.service()
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/task.py", line 173, in service
self.execute()
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/task.py", line 380, in execute
app_iter = self.channel.server.application(env, start_response)
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/pyramid/router.py", line 187, in __call__
response = self.handle_request(request)
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/pyramid/tweens.py", line 20, in excview_tween
response = handler(request)
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/pyramid/router.py", line 164, in handle_request
response = view_callable(context, request)
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/pyramid/config/views.py", line 358, in viewresult_to_response
result = view(context, request)
File "/home/alienoid/.virtualenvs/mypyramid/lib/python2.7/site-packages/pyramid/config/views.py", line 462, in _requestonly_view
response = view(request)
File "testcallback.py", line 20, in hello
raise Exception('Check me in finished callback!')
Exception: Check me in finished callback!

The offending part is in [*pyramid/tweens.py*](https://github.com/Pylons/pyramid/blob/master/pyramid/tweens.py#L38) finally block that deletes **exception** and **exc_info** from request that is being passed later on to the finished callback.

```python
finally:
# prevent leakage (wrt exc_info)
if 'exc_info' in attrs:
del attrs['exc_info']
if 'exception' in attrs:
del attrs['exception']
```