Skip to content

Windows: use Winsock values for errno socket constants (PROD-1626 part 1) - #115

Merged
icanhasmath merged 1 commit into
2.7from
prod-1626-winsock-errno
Oct 28, 2026
Merged

icanhasmath merged 1 commit into
2.7from
prod-1626-winsock-errno

Conversation

@icanhasmath

Copy link
Copy Markdown

PROD-1626 part 1: on Windows, errno's socket constants now use the Winsock values, so they match the errors sockets actually report.

Tracking: Linear PROD-1626 (follow-up from #60), for 2.7.18.16rc2 alongside #114.

Problem

Our Windows 2.7 builds use Visual Studio 14+. VS2010 and later define their own ECONNRESET, EWOULDBLOCK, ETIMEDOUT and 22 other socket error numbers in errno.h, and errnomodule.c prefers those over its WSAE* fallbacks. Sockets report the Winsock codes, so on 2.7.18.14 and 2.7.18.16rc1:

>>> errno.EWOULDBLOCK, errno.ECONNRESET
(140, 108)
>>> s.connect_ex(...)   # non-blocking
10035                   # WSAEWOULDBLOCK

Code that compares a socket error with an errno constant never matches. That is why test_ssl's test_connect_ex_error, test_non_blocking_connect_ex and test_timeout_connect_ex fail on the Windows rc1 build.

Change

Modules/errnomodule.c undefines the 25 VS2010 constants on MS_WINDOWS before building the module table, exactly as CPython 3.5+ does, so the existing WSAE* fallbacks are used. I checked each of the 25 has a fallback, so no name disappears.

  • Objects/exceptions.c is not touched: 2.7.18.10 dev #60 changed it, but 2.7's exceptions.c uses none of these constants (3.x needs it for the OSError subclasses).
  • socketmodule.c already uses the WSAE* codes directly on Windows.
  • The 2.7.18.14 workarounds in ssl (56c572be6bd, WSAENOTCONN) and asyncore (49e394606b8) stay. They keep working because both spellings are now the same value. No test skips were added for this, so there is nothing to re-enable.
  • New test_errno.WinsockErrnoTests (Windows-only): each constant equals its WSA value, and a non-blocking connect_ex() returns errno.EWOULDBLOCK.
  • NEWS entry in Misc/NEWS.d/2.7.18.16.rst (Windows section).

Testing

  • Windows x64: compiled this errnomodule.c with VS 2022 17.14 (the Platform's toolchain, MSC v.1944) as an extension against the 2.7.18.16rc1 runtime. All 25 constants equal their WSAE* values, connect_ex() returns errno.EWOULDBLOCK (10035), no name is lost, no non-socket value changes, and errorcode round-trips. The full Windows regression run happens on the rc2 build.
  • Linux: no change. test_errno passes, and the new class is skipped.

Compatibility

Only the values of these 25 names change, and only on Windows. Code that hard-coded 140/108 etc. for socket errors was already wrong, because sockets never return them. The C runtime never returns these codes for file operations.

PROD-1626 part 2 (distutils VS 14+ compiler detection) is separate and needs a VS toolchain test, so it is planned for a later release.

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 (56c572b) and asyncore
(49e3946) 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 <noreply@anthropic.com>

@ezequielp-activestate ezequielp-activestate left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. This is the right fix, and it matches upstream exactly.

What I checked

  • The 25 #undefs are the same list, in the same order, as upstream's own fix. Upstream added it in 401f9f3 ("Fix python#13210. Port the Windows build from VS2008 to VS2010"), which has been in every 3.x since.
  • Every one of the 25 names already has a WSA* fallback (inscode(d, ds, de, "<NAME>", WSA<NAME>, ...)) further down errnomodule.c, so no attribute disappears from errno.
  • The change is confined to errnomodule.c under MS_WINDOWS, so no other C code sees different values. 2.7's PC/errmap.h (winerror_to_errno) maps only to values ≤ 41, so a file or OS error can never carry one of the old VS2010 values (100–140) that Python code would now fail to match.
  • On Linux (2.7 container, with this PR's Lib/test), test_errno passes: 5 run, and the 2 Windows tests are skipped.

🟡 Non-blocking: test_socket_error_matches_errno assumes a non-blocking connect to 10.255.255.1 is still pending. On a Windows machine with no default route, connect_ex fails at once with WSAENETUNREACH (10051) instead of WSAEWOULDBLOCK. Accepting (errno.EWOULDBLOCK, errno.ENETUNREACH), or skipping when the result is ENETUNREACH, would keep it from failing on an isolated build agent.

@icanhasmath
icanhasmath merged commit 2741996 into 2.7 Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants