mirror of https://github.com/zulip/zulip.git
tornado: Call close() on Django HttpResponse objects.
This is necessary to break the uncollectable reference cycle created by our ‘request_notes.saved_response = json_response(…)’, Django’s ‘response._resource_closers.append(request.close)’, and Python’s https://bugs.python.org/issue44680. Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
7cf859882d
commit
fd0ab7c4ec
|
@ -148,10 +148,9 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
|||
|
||||
def get(self, *args: Any, **kwargs: Any) -> None:
|
||||
request = self.convert_tornado_request_to_django_request()
|
||||
response = self.get_response(request)
|
||||
|
||||
try:
|
||||
response = self.get_response(request)
|
||||
|
||||
if hasattr(response, "asynchronous"):
|
||||
# We import async_request_timer_restart during runtime
|
||||
# to avoid cyclic dependency with zerver.lib.request
|
||||
|
@ -165,22 +164,21 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
|||
# consumed by the request when it eventually returns a
|
||||
# response and is logged.
|
||||
async_request_timer_stop(request)
|
||||
return
|
||||
else:
|
||||
# For normal/synchronous requests that don't end up
|
||||
# long-polling, we just need to write the HTTP
|
||||
# response that Django prepared for us via Tornado.
|
||||
|
||||
# Mark this handler ID as finished for Zulip's own tracking.
|
||||
clear_handler_by_id(self.handler_id)
|
||||
|
||||
self.write_django_response_as_tornado_response(response)
|
||||
finally:
|
||||
# Tell Django that we're done processing this request on
|
||||
# the Django side; this triggers cleanup work like
|
||||
# resetting the urlconf and any cache/database
|
||||
# connections.
|
||||
signals.request_finished.send(sender=self.__class__)
|
||||
|
||||
# For normal/synchronous requests that don't end up
|
||||
# long-polling, we fall through to here and just need to write
|
||||
# the HTTP response that Django prepared for us via Tornado.
|
||||
|
||||
# Mark this handler ID as finished for Zulip's own tracking.
|
||||
clear_handler_by_id(self.handler_id)
|
||||
|
||||
self.write_django_response_as_tornado_response(response)
|
||||
response.close()
|
||||
|
||||
def head(self, *args: Any, **kwargs: Any) -> None:
|
||||
self.get(*args, **kwargs)
|
||||
|
@ -258,16 +256,12 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
|||
res_type=result_dict["result"], data=result_dict, status=self.get_status()
|
||||
)
|
||||
|
||||
response = self.get_response(request)
|
||||
try:
|
||||
response = self.get_response(request)
|
||||
# Explicitly mark requests as varying by cookie, since the
|
||||
# middleware will not have seen a session access
|
||||
patch_vary_headers(response, ("Cookie",))
|
||||
self.write_django_response_as_tornado_response(response)
|
||||
finally:
|
||||
# Tell Django we're done processing this request
|
||||
#
|
||||
# TODO: Investigate whether this (and other call points in
|
||||
# this file) should be using response.close() instead.
|
||||
signals.request_finished.send(sender=self.__class__)
|
||||
|
||||
self.write_django_response_as_tornado_response(response)
|
||||
response.close()
|
||||
|
|
Loading…
Reference in New Issue