summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorJames Thorniley <james.thorniley@mixcloud.com>2024-01-04 13:14:30 +0000
committerNatalia <124304+nessita@users.noreply.github.com>2024-01-31 14:45:44 -0300
commitf1fbd061ac34f0afdaac4a5c7db099c39b43cb4a (patch)
treea6f0f2d66f987a99e3303f91c757afefc436e045 /django
parentbbb9ef3c62674e94ad8e6556933b112d84891f3d (diff)
[5.0.x] Fixed #35059 -- Ensured that ASGIHandler always sends the request_finished signal.
Prior to this work, when async tasks that process the request are cancelled due to receiving an early "http.disconnect" ASGI message, the request_finished signal was not being sent, potentially leading to resource leaks (such as database connections). This branch ensures that the request_finished signal is sent even in the case of early termination of the response. Regression in 64cea1e48f285ea2162c669208d95188b32bbc82. Co-authored-by: Natalia <124304+nessita@users.noreply.github.com> Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es> Backport of 11393ab1316f973c5fbb534305750740d909b4e4 from main
Diffstat (limited to 'django')
-rw-r--r--django/core/handlers/asgi.py18
1 files changed, 16 insertions, 2 deletions
diff --git a/django/core/handlers/asgi.py b/django/core/handlers/asgi.py
index 7b0086fb76..3af080599a 100644
--- a/django/core/handlers/asgi.py
+++ b/django/core/handlers/asgi.py
@@ -186,11 +186,18 @@ class ASGIHandler(base.BaseHandler):
if request is None:
body_file.close()
await self.send_response(error_response, send)
+ await sync_to_async(error_response.close)()
return
async def process_request(request, send):
response = await self.run_get_response(request)
- await self.send_response(response, send)
+ try:
+ await self.send_response(response, send)
+ except asyncio.CancelledError:
+ # Client disconnected during send_response (ignore exception).
+ pass
+
+ return response
# Try to catch a disconnect while getting response.
tasks = [
@@ -221,6 +228,14 @@ class ASGIHandler(base.BaseHandler):
except asyncio.CancelledError:
# Task re-raised the CancelledError as expected.
pass
+
+ try:
+ response = tasks[1].result()
+ except asyncio.CancelledError:
+ await signals.request_finished.asend(sender=self.__class__)
+ else:
+ await sync_to_async(response.close)()
+
body_file.close()
async def listen_for_disconnect(self, receive):
@@ -346,7 +361,6 @@ class ASGIHandler(base.BaseHandler):
"more_body": not last,
}
)
- await sync_to_async(response.close, thread_sensitive=True)()
@classmethod
def chunk_bytes(cls, data):