From 774601966186b002918b5169cdea02be0d0a255d Mon Sep 17 00:00:00 2001 From: Jeffrey 'Alex' Clark Date: Mon, 5 Oct 2026 16:46:36 -0400 Subject: [PATCH] PYTHON-6143 Fix TestKmsTLSOptions on Windows On Windows the async SSL receive path busy-polls a non-blocking socket, because the default Windows asyncio event loop does not support loop.add_reader. On Python 3.14.7+ a non-blocking recv_into raises raw ConnectionResetError (WinError 10054) when the peer closes without TLS close_notify, as the mock KMS servers do, instead of returning 0 or raising SSLError. The raw error escaped the BLOCKING_IO_ERRORS handling and surfaced as a different error than the graceful close the KMS path expects. Map the reset to OSError('connection closed') in that loop. Co-Authored-By: Claude Code --- pymongo/network_layer.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pymongo/network_layer.py b/pymongo/network_layer.py index 9909add8e0..e368da81a8 100644 --- a/pymongo/network_layer.py +++ b/pymongo/network_layer.py @@ -167,6 +167,12 @@ async def _async_socket_receive_ssl( except BLOCKING_IO_ERRORS: await asyncio.sleep(backoff) read = 0 + except (ConnectionResetError, ConnectionAbortedError) as exc: + # On Python 3.14.7+ a peer that closes without TLS close_notify + # (e.g. the mock KMS servers) raises this instead of returning + # 0 or raising SSLError. Report the graceful close the KMS + # path expects (PYTHON-6143). + raise OSError("connection closed") from exc if read > 0: backoff = max(backoff / 2, 0.001) else: