Widen the port window a test binds in where the kernel does not pick it
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Has been cancelled

bindwithrange() honours a range by setting IP_LOCAL_PORT_RANGE where it
exists, which leaves the kernel to pick a port inside it and skip the ones
still closing. Everywhere else it binds a port out of the range at random,
ten times, and lets the system choose when all ten are taken.

A port which carried a connection cannot be bound again until that close
completes - four minutes of it on Windows - so a window of fifty ports
shared by three services in one configuration can have too few left, and
the connection then binds outside the range and the case fails. The window
is five hundred ports there instead. The Linux one is unchanged: the
kernel picks from it and needs no room to spare.
This commit is contained in:
Vladimir Dubrovin 2026-08-29 22:48:39 +03:00
parent 2b8845f65a
commit 48d72538e1

View File

@ -14,12 +14,19 @@ def _windows():
net.ipv4.ip_local_port_range; a window outside it is ignored and an
ordinary ephemeral port is used, so a fixed low window would be
measuring the kernel's own choice rather than the setting.
Everywhere else the range is honoured by binding a port out of it at
random, ten times before giving up and letting the system choose. A port
which carried a connection a moment ago cannot be bound again while it
waits out its close - four minutes of it on Windows - so the window has
to be wide enough that ten tries do not all land on one. The window the
kernel picks from on Linux needs no such room, since it skips them.
"""
try:
with open("/proc/sys/net/ipv4/ip_local_port_range") as fp:
low, high = (int(part) for part in fp.read().split()[:2])
except (OSError, ValueError):
return (21400, 21449), (21500, 21549)
return (21400, 21899), (22000, 22499)
base = low + 1000 if low + 1150 <= high else low
return (base, base + 49), (base + 100, base + 149)