Replace random.randint port picks with OS-assigned ephemeral ports#703
Merged
gijzelaerr merged 1 commit intomasterfrom Apr 21, 2026
Merged
Replace random.randint port picks with OS-assigned ephemeral ports#703gijzelaerr merged 1 commit intomasterfrom
gijzelaerr merged 1 commit intomasterfrom
Conversation
The post-merge CI for #701 hit Errno 98 ("Address already in use") on ubuntu-24.04 / py3.14 inside test_server_context_manager. Root cause: tests picked ports via random.randint over narrow ranges (5k-20k ports) with no collision check, so two concurrent server starts could grab the same port, and re-runs on the same runner hit TIME_WAIT lingers. Fix: bind a throwaway socket to port 0, read the OS-assigned ephemeral port, close, and pass it to the server. The ephemeral pool is tens of thousands wide and the OS guarantees the port is free at the moment of pick — much smaller collision window than a 1-in-5000 random draw. snap7.server already sets SO_REUSEADDR so TIME_WAIT lingers don't bite either. One helper (`get_free_tcp_port`) lives in tests/conftest.py and is reused by test_s7_unified, test_optimizer, and test_stress. Added tests/__init__.py so `from .conftest import ...` works. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the
Errno 98: Address already in useflake that bittest_server_context_managerin the post-merge CI run for #701. Root cause: test fixtures picked TCP ports viarandom.randintover narrow ranges (5k-20k ports wide) with no free-check. Under concurrent server starts or rapid re-runs the draw collides.Fix: bind a throwaway socket to port 0, read the OS-assigned ephemeral port, close it, and pass the number to the test server. The ephemeral pool is tens of thousands wide and the OS guarantees the port was free at pick time — much smaller collision window than the previous random draws.
snap7.serveralready setsSO_REUSEADDR, so TIME_WAIT lingers from a prior run don't bite either.One helper (
get_free_tcp_port) lives intests/conftest.pyand is reused bytest_s7_unified,test_optimizer, andtest_stress. Added an emptytests/__init__.pysofrom .conftest import get_free_tcp_portworks (the directory was already treated as a package by pytest; this just makes the relative import legal).Test plan
test_server_context_managerrun 10 times in a row — 10/10 pass🤖 Generated with Claude Code