From 731ae17e72df0b42a7f33a69e0e21096d6d99e3c Mon Sep 17 00:00:00 2001 From: Timofey Ivankov Date: Sun, 16 Aug 2026 22:06:28 +0300 Subject: [PATCH] gh-155888: Fix asyncio writelines() hanging on an empty last chunk --- Lib/asyncio/selector_events.py | 6 +++++- Lib/test/test_asyncio/test_events.py | 13 +++++++++++++ .../2026-08-16-11-38-17.gh-issue-155888.pO-nAp.rst | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-08-16-11-38-17.gh-issue-155888.pO-nAp.rst diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 0c96e81cce0bd5..3aac81215dc0ae 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -1183,7 +1183,11 @@ def writelines(self, list_of_data): self._conn_lost += 1 return - self._buffer.extend([memoryview(data) for data in list_of_data]) + # gh-155888: an empty chunk can never be drained, so never buffer it + self._buffer.extend( + [memoryview(data) for data in list_of_data if data]) + if not self._buffer: + return self._write_ready() # If the entire buffer couldn't be written, register a write handler if self._buffer: diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 888e8b4d11b978..1ee39b0fac3ad6 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -560,6 +560,19 @@ def writer(data): r.close() self.assertEqual(read, data) + def test_writelines_empty_chunk(self): + # gh-155888: an empty chunk can never be drained, so never buffer it + rsock, wsock = socket.socketpair() + self.addCleanup(rsock.close) + + async def main(): + reader, writer = await asyncio.open_connection(sock=wsock) + writer.writelines([b'data', b'']) + writer.close() + await asyncio.wait_for(writer.wait_closed(), support.SHORT_TIMEOUT) + + self.loop.run_until_complete(main()) + @unittest.skipUnless(hasattr(signal, 'SIGKILL'), 'No SIGKILL') def test_add_signal_handler(self): caught = 0 diff --git a/Misc/NEWS.d/next/Library/2026-08-16-11-38-17.gh-issue-155888.pO-nAp.rst b/Misc/NEWS.d/next/Library/2026-08-16-11-38-17.gh-issue-155888.pO-nAp.rst new file mode 100644 index 00000000000000..df3db71b912e1c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-16-11-38-17.gh-issue-155888.pO-nAp.rst @@ -0,0 +1,2 @@ +Fix :meth:`asyncio.WriteTransport.writelines` hanging the transport when the +last data chunk is empty.