Commit a78c15f8 authored by Tres Seaver's avatar Tres Seaver

Prevent leaked connections when broken 'EndRequestEvent' subscribers raise.

Fixes #16 on the master branch.
parent 3710b7fe
...@@ -11,6 +11,9 @@ http://docs.zope.org/zope2/ ...@@ -11,6 +11,9 @@ http://docs.zope.org/zope2/
Bugs Fixed Bugs Fixed
++++++++++ ++++++++++
- Issue #16: prevent leaked connections when broken ``EndRequestEvent``
subscribers raise exceptions.
- Ensure that the ``WSGIPublisher`` begins and ends an *interaction* - Ensure that the ``WSGIPublisher`` begins and ends an *interaction*
at the request/response barrier. This is required for instance for at the request/response barrier. This is required for instance for
the ``checkPermission`` call to function without an explicit the ``checkPermission`` call to function without an explicit
......
...@@ -215,7 +215,9 @@ class BaseRequest: ...@@ -215,7 +215,9 @@ class BaseRequest:
self._held=None self._held=None
def close(self): def close(self):
try:
notify(EndRequestEvent(None, self)) notify(EndRequestEvent(None, self))
finally:
# subscribers might need the zodb, so `clear` must come afterwards # subscribers might need the zodb, so `clear` must come afterwards
# (since `self._held=None` might close the connection, see above) # (since `self._held=None` might close the connection, see above)
self.clear() self.clear()
......
...@@ -424,6 +424,22 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory): ...@@ -424,6 +424,22 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
r = self._makeOne(root) r = self._makeOne(root)
self.assertRaises(NotFound, r.traverse, 'folder/simpleFrozenSet') self.assertRaises(NotFound, r.traverse, 'folder/simpleFrozenSet')
def test_close_w_broken_subscriber(self):
# See: https://github.com/zopefoundation/Zope/issues/16
from zope.event import subscribers
root, folder = self._makeRootAndFolder()
r = self._makeOne(root)
r.other['foo'] = 'Foo'
BEFORE = subscribers[:]
def _broken(event):
raise ValueError("I'm broken")
subscribers.append(_broken)
try:
self.assertRaises(ValueError, r.close)
finally:
subscribers[:] = BEFORE
self.assertEqual(r.other, {})
def test_hold_after_close(self): def test_hold_after_close(self):
# Request should no longer accept holds after it has been closed # Request should no longer accept holds after it has been closed
root, folder = self._makeRootAndFolder() root, folder = self._makeRootAndFolder()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment