]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] GH-110894: Call loop exception handler for exceptions in client_connected_cb...
authorKumar Aditya <kumaraditya@python.org>
Thu, 2 Nov 2023 08:18:49 +0000 (13:48 +0530)
committerGitHub <noreply@github.com>
Thu, 2 Nov 2023 08:18:49 +0000 (08:18 +0000)
Call loop exception handler for exceptions in `client_connected_cb` of `asyncio.start_server` so that applications can handle it..
(cherry picked from commit 229f44d353c71185414a072017f46f125676bdd6)

Lib/asyncio/streams.py
Lib/test/test_asyncio/test_streams.py
Misc/NEWS.d/next/Library/2023-11-01-14-03-24.gh-issue-110894.7-wZxC.rst [new file with mode: 0644]

index aff081a1e0d02cad06aaba091fc267ac4841942e..f63eeca2a7719a592dae9a0700093ee8f0cb9a26 100644 (file)
@@ -244,7 +244,19 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
             res = self._client_connected_cb(reader,
                                             self._stream_writer)
             if coroutines.iscoroutine(res):
+                def callback(task):
+                    exc = task.exception()
+                    if exc is not None:
+                        self._loop.call_exception_handler({
+                            'message': 'Unhandled exception in client_connected_cb',
+                            'exception': exc,
+                            'transport': transport,
+                        })
+                        transport.close()
+
                 self._task = self._loop.create_task(res)
+                self._task.add_done_callback(callback)
+
             self._strong_reader = None
 
     def connection_lost(self, exc):
index 7f9dc6218083581aa5f08e746ef4e2c35fdcd54a..a0ed5ab798676829f9d4df59963fa6cd7dddd134 100644 (file)
@@ -1074,6 +1074,35 @@ os.close(fd)
 
         self.assertEqual(messages, [])
 
+    def test_unhandled_exceptions(self) -> None:
+        port = socket_helper.find_unused_port()
+
+        messages = []
+        self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx))
+
+        async def client():
+            rd, wr = await asyncio.open_connection('localhost', port)
+            wr.write(b'test msg')
+            await wr.drain()
+            wr.close()
+            await wr.wait_closed()
+
+        async def main():
+            async def handle_echo(reader, writer):
+                raise Exception('test')
+
+            server = await asyncio.start_server(
+                handle_echo, 'localhost', port)
+            await server.start_serving()
+            await client()
+            server.close()
+            await server.wait_closed()
+
+        self.loop.run_until_complete(main())
+
+        self.assertEqual(messages[0]['message'],
+                         'Unhandled exception in client_connected_cb')
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2023-11-01-14-03-24.gh-issue-110894.7-wZxC.rst b/Misc/NEWS.d/next/Library/2023-11-01-14-03-24.gh-issue-110894.7-wZxC.rst
new file mode 100644 (file)
index 0000000..c59fe6b
--- /dev/null
@@ -0,0 +1 @@
+Call loop exception handler for exceptions in ``client_connected_cb`` of :func:`asyncio.start_server` so that applications can handle it. Patch by Kumar Aditya.