summaryrefslogtreecommitdiff
path: root/Lib
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2019-05-19 09:28:38 -0700
committerBerker Peksag <berker.peksag@gmail.com>2019-05-19 19:28:38 +0300
commitf393e8eb463d60ce559982613429568c518ab8d9 (patch)
tree8fe7d65f10edce13dea14876d22d048553f837f6 /Lib
parent3645d29a1dc2102fdb0f5f0c0129ff2295bcd768 (diff)
downloadcpython-git-f393e8eb463d60ce559982613429568c518ab8d9.tar.gz
bpo-29183: Fix double exceptions in wsgiref.handlers.BaseHandler (GH-12914)
(cherry picked from commit 7c59362a15dfce538512ff1fce4e07d33a925cfb) Co-authored-by: Berker Peksag <berker.peksag@gmail.com>
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_wsgiref.py25
-rw-r--r--Lib/wsgiref/handlers.py11
2 files changed, 35 insertions, 1 deletions
diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py
index 5502ece576..7650e1392c 100644
--- a/Lib/test/test_wsgiref.py
+++ b/Lib/test/test_wsgiref.py
@@ -798,6 +798,31 @@ class HandlerTests(TestCase):
self.assertFalse(stderr.getvalue())
+ def testDontResetInternalStateOnException(self):
+ class CustomException(ValueError):
+ pass
+
+ # We are raising CustomException here to trigger an exception
+ # during the execution of SimpleHandler.finish_response(), so
+ # we can easily test that the internal state of the handler is
+ # preserved in case of an exception.
+ class AbortingWriter:
+ def write(self, b):
+ raise CustomException
+
+ stderr = StringIO()
+ environ = {"SERVER_PROTOCOL": "HTTP/1.0"}
+ h = SimpleHandler(BytesIO(), AbortingWriter(), stderr, environ)
+ h.run(hello_app)
+
+ self.assertIn("CustomException", stderr.getvalue())
+
+ # Test that the internal state of the handler is preserved.
+ self.assertIsNotNone(h.result)
+ self.assertIsNotNone(h.headers)
+ self.assertIsNotNone(h.status)
+ self.assertIsNotNone(h.environ)
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/wsgiref/handlers.py b/Lib/wsgiref/handlers.py
index f04cef9b9d..eee3f948c7 100644
--- a/Lib/wsgiref/handlers.py
+++ b/Lib/wsgiref/handlers.py
@@ -183,7 +183,16 @@ class BaseHandler:
for data in self.result:
self.write(data)
self.finish_content()
- finally:
+ except:
+ # Call close() on the iterable returned by the WSGI application
+ # in case of an exception.
+ if hasattr(self.result, 'close'):
+ self.result.close()
+ raise
+ else:
+ # We only call close() when no exception is raised, because it
+ # will set status, result, headers, and environ fields to None.
+ # See bpo-29183 for more details.
self.close()