From 5f433699d2467908f73f13af99d99e7ae3a06c24 Mon Sep 17 00:00:00 2001 From: icanhasmath Date: Wed, 28 Oct 2026 17:51:56 -0500 Subject: [PATCH] errno: use the Winsock values for socket errno constants on Windows Visual Studio 2010 and later define their own ECONNRESET, EWOULDBLOCK, ETIMEDOUT and 22 other socket error numbers in errno.h. errnomodule.c prefers those over the WSAE* fallbacks, so on our VS 14+ builds errno.EWOULDBLOCK is 140 while a socket reports WSAEWOULDBLOCK (10035), and code that compares a socket error with an errno constant never matches. Undefine the VS2010 constants before the module table, as CPython 3.5+ does, so the WSAE* fallbacks are used. The socket module's own Windows paths already use the WSAE* codes directly, and Objects/exceptions.c in 2.7 uses none of these constants, so errnomodule.c is the only change. The ssl (56c572be6bd) and asyncore (49e394606b8) workarounds keep working: both spellings are now the same value. Verified by compiling this errnomodule.c with VS 2022 (17.14) against the 2.7.18.16rc1 Windows x64 runtime: all 25 constants equal their WSAE* values, a non-blocking connect_ex() returns errno.EWOULDBLOCK, and no name or non-socket value changes. PROD-1626 part 1. Co-Authored-By: Claude Opus 5.5 --- Lib/test/test_errno.py | 33 ++++++++++++++++++++++++++++++++- Misc/NEWS.d/2.7.18.16.rst | 16 ++++++++++++++++ Modules/errnomodule.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_errno.py b/Lib/test/test_errno.py index 7a37d3a6a59a09..a682a7c1e7c525 100644 --- a/Lib/test/test_errno.py +++ b/Lib/test/test_errno.py @@ -3,6 +3,7 @@ """ import errno +import sys from test import test_support import unittest @@ -31,8 +32,38 @@ def test_attributes_in_errorcode(self): 'no %s attr in errno.errorcode' % attribute) +@unittest.skipUnless(sys.platform == 'win32', 'Windows specific') +class WinsockErrnoTests(unittest.TestCase): + + # VS2010+ errno.h defines its own values for these; sockets report the + # Winsock ones, so the errno module must use those. + names = ['EADDRINUSE', 'EADDRNOTAVAIL', 'EAFNOSUPPORT', 'EALREADY', + 'ECONNABORTED', 'ECONNREFUSED', 'ECONNRESET', 'EDESTADDRREQ', + 'EHOSTUNREACH', 'EINPROGRESS', 'EISCONN', 'ELOOP', 'EMSGSIZE', + 'ENETDOWN', 'ENETRESET', 'ENETUNREACH', 'ENOBUFS', 'ENOPROTOOPT', + 'ENOTCONN', 'ENOTSOCK', 'EOPNOTSUPP', 'EPROTONOSUPPORT', + 'EPROTOTYPE', 'ETIMEDOUT', 'EWOULDBLOCK'] + + def test_socket_constants_are_winsock_values(self): + for name in self.names: + self.assertEqual(getattr(errno, name), getattr(errno, 'WSA' + name), + name) + + def test_socket_error_matches_errno(self): + import socket + s = socket.socket() + try: + s.setblocking(False) + # Connecting to a non-routable address does not complete at once. + self.assertEqual(s.connect_ex(('10.255.255.1', 80)), + errno.EWOULDBLOCK) + finally: + s.close() + + def test_main(): - test_support.run_unittest(ErrnoAttributeTests, ErrorcodeTests) + test_support.run_unittest(ErrnoAttributeTests, ErrorcodeTests, + WinsockErrnoTests) if __name__ == '__main__': diff --git a/Misc/NEWS.d/2.7.18.16.rst b/Misc/NEWS.d/2.7.18.16.rst index 58a4d70473933e..b938f37ed827c1 100644 --- a/Misc/NEWS.d/2.7.18.16.rst +++ b/Misc/NEWS.d/2.7.18.16.rst @@ -256,3 +256,19 @@ Removed an unused function from ``Modules/socketmodule.c`` that referenced a symbol Python 2.7 does not build, so ``-O0`` and ``--with-pydebug`` builds produced a ``_socket`` module (and :mod:`ssl`) that failed to import. ``test_ssl`` no longer needs the third-party ``mock`` package. + +.. bpo: 0 +.. date: 2026-10-28 +.. nonce: as1916 +.. release date: 2026-10-28 +.. original section: Windows +.. section: Windows + +Use the Winsock values for socket errno constants on Windows + +Visual Studio 2010 and later define their own ``ECONNRESET``, +``EWOULDBLOCK``, ``ETIMEDOUT`` and other socket error numbers in +``errno.h``, but Windows sockets report the Winsock ``WSAE*`` codes, so +``errno.EWOULDBLOCK`` (140) never matched a socket error (10035). The +:mod:`errno` module now uses the Winsock values for these 25 constants, as +Python 3.5 and later do. diff --git a/Modules/errnomodule.c b/Modules/errnomodule.c index 87ebab013a0b7c..3868fe8a93f8ac 100644 --- a/Modules/errnomodule.c +++ b/Modules/errnomodule.c @@ -6,6 +6,34 @@ /* Windows socket errors (WSA*) */ #ifdef MS_WINDOWS #include +/* The following constants were added to errno.h in VS2010 but have + preferred WSA equivalents: the socket module reports Winsock errors, + so errno.ECONNRESET and friends must be the WSAE* values (as in 3.5+). */ +#undef EADDRINUSE +#undef EADDRNOTAVAIL +#undef EAFNOSUPPORT +#undef EALREADY +#undef ECONNABORTED +#undef ECONNREFUSED +#undef ECONNRESET +#undef EDESTADDRREQ +#undef EHOSTUNREACH +#undef EINPROGRESS +#undef EISCONN +#undef ELOOP +#undef EMSGSIZE +#undef ENETDOWN +#undef ENETRESET +#undef ENETUNREACH +#undef ENOBUFS +#undef ENOPROTOOPT +#undef ENOTCONN +#undef ENOTSOCK +#undef EOPNOTSUPP +#undef EPROTONOSUPPORT +#undef EPROTOTYPE +#undef ETIMEDOUT +#undef EWOULDBLOCK #endif /*