diff --git a/maint/circlerefs/circlerefs.py b/maint/circlerefs/circlerefs.py index 0fb59c6f..fe91a09b 100644 --- a/maint/circlerefs/circlerefs.py +++ b/maint/circlerefs/circlerefs.py @@ -70,8 +70,16 @@ class DummyHandler(web.RequestHandler): self.write('ok\n') +class DummyAsyncHandler(web.RequestHandler): + @gen.coroutine + def get(self): + raise web.Finish('ok\n') + + + application = web.Application([ (r'/dummy/', DummyHandler), + (r'/dummyasync/', DummyAsyncHandler), (r'/collect/', CollectHandler), ], debug=True) @@ -90,11 +98,12 @@ def main(): # poke at it with a browser. client = httpclient.AsyncHTTPClient() yield client.fetch('http://127.0.0.1:8888/dummy/') + yield client.fetch('http://127.0.0.1:8888/dummyasync/', raise_error=False) # Now report on the results. - gc.collect() resp = yield client.fetch('http://127.0.0.1:8888/collect/') print(resp.body) + if __name__ == "__main__": ioloop.IOLoop.current().run_sync(main) diff --git a/tornado/gen.py b/tornado/gen.py index 533ccb74..b56b0efd 100644 --- a/tornado/gen.py +++ b/tornado/gen.py @@ -290,7 +290,11 @@ def _make_coroutine_wrapper(func, replace_callback): result = _value_from_stopiteration(e) except Exception: future_set_exc_info(future, sys.exc_info()) - return future + try: + return future + finally: + # Avoid circular references + future = None else: if isinstance(result, GeneratorType): # Inline the first iteration of Runner.run. This lets us diff --git a/tornado/web.py b/tornado/web.py index 0cc34b8e..f2749f7c 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -1537,6 +1537,9 @@ class RequestHandler(object): self._handle_request_exception(e) except Exception: app_log.error("Exception in exception handler", exc_info=True) + finally: + # Unset result to avoid circular references + result = None if (self._prepared_future is not None and not self._prepared_future.done()): # In case we failed before setting _prepared_future, do it