Skip to content

Commit f393e8e

Browse files
bpo-29183: Fix double exceptions in wsgiref.handlers.BaseHandler (GH-12914)
(cherry picked from commit 7c59362) Co-authored-by: Berker Peksag <[email protected]>
1 parent 3645d29 commit f393e8e

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

Lib/test/test_wsgiref.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,31 @@ def write(self, b):
798798

799799
self.assertFalse(stderr.getvalue())
800800

801+
def testDontResetInternalStateOnException(self):
802+
class CustomException(ValueError):
803+
pass
804+
805+
# We are raising CustomException here to trigger an exception
806+
# during the execution of SimpleHandler.finish_response(), so
807+
# we can easily test that the internal state of the handler is
808+
# preserved in case of an exception.
809+
class AbortingWriter:
810+
def write(self, b):
811+
raise CustomException
812+
813+
stderr = StringIO()
814+
environ = {"SERVER_PROTOCOL": "HTTP/1.0"}
815+
h = SimpleHandler(BytesIO(), AbortingWriter(), stderr, environ)
816+
h.run(hello_app)
817+
818+
self.assertIn("CustomException", stderr.getvalue())
819+
820+
# Test that the internal state of the handler is preserved.
821+
self.assertIsNotNone(h.result)
822+
self.assertIsNotNone(h.headers)
823+
self.assertIsNotNone(h.status)
824+
self.assertIsNotNone(h.environ)
825+
801826

802827
if __name__ == "__main__":
803828
unittest.main()

Lib/wsgiref/handlers.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,16 @@ def finish_response(self):
183183
for data in self.result:
184184
self.write(data)
185185
self.finish_content()
186-
finally:
186+
except:
187+
# Call close() on the iterable returned by the WSGI application
188+
# in case of an exception.
189+
if hasattr(self.result, 'close'):
190+
self.result.close()
191+
raise
192+
else:
193+
# We only call close() when no exception is raised, because it
194+
# will set status, result, headers, and environ fields to None.
195+
# See bpo-29183 for more details.
187196
self.close()
188197

189198

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix double exceptions in :class:`wsgiref.handlers.BaseHandler` by calling
2+
its :meth:`~wsgiref.handlers.BaseHandler.close` method only when no
3+
exception is raised.

0 commit comments

Comments
 (0)