Skip to content

testing: drop SO_REUSEADDR from the port-availability probe#214

Merged
chen3feng merged 1 commit into
masterfrom
fix/port-probe-so-reuseaddr
Jul 3, 2026
Merged

testing: drop SO_REUSEADDR from the port-availability probe#214
chen3feng merged 1 commit into
masterfrom
fix/port-probe-so-reuseaddr

Conversation

@chen3feng

Copy link
Copy Markdown
Collaborator

Problem

testing::PickAvailablePort() / PickAvailableEndpoint() probe a candidate port by binding to it. The probe set SO_REUSEADDR before binding 0.0.0.0:port. On macOS/BSD SO_REUSEADDR lets that bind succeed even while another socket already holds 127.0.0.1:port — so the probe reports an occupied port as free. The caller then binds its real server to the same port and fails:

W socket.cc:150] Cannot bind socket to [127.0.0.1:5136]. : Address already in use [48]
F server.cc:226] Check failed: !!fd Cannot create listener.

This only bites under parallel test execution, where sibling tests hold ports concurrently (observed on logging_test running alongside server_test / server_group_test / integration_test). In isolation the test always passes.

Fix

Drop SO_REUSEADDR from the probe. An availability probe must observe the port exactly as a fresh server bind would; with the override it doesn't. Without it, an occupied port is correctly rejected and PickAvailablePort() just retries another random port (no functional loss).

Verification

  • Deterministic repro: occupy 127.0.0.1:P (no reuse); probe 0.0.0.0:P with SO_REUSEADDR reports AVAILABLE (false positive), without it reports occupied (correct).
  • Stress: ran the four port-grabbing rpc tests in parallel across many rounds — 0 flakes after the fix.

🤖 Generated with Claude Code

PickAvailablePort()/PickAvailableEndpoint() probe a candidate port by
binding to it, but the probe socket set SO_REUSEADDR before binding
0.0.0.0:port. On macOS/BSD that lets the probe succeed even while another
process (e.g. a sibling test's server) already holds 127.0.0.1:port,
falsely reporting the port as free. The caller then binds its real server
to the same port and fails with EADDRINUSE.

This only surfaces under parallel test execution, where multiple tests
grab ports concurrently -- e.g. logging_test failing with "Cannot bind
socket to [127.0.0.1:5136]. : Address already in use" when run alongside
server_test/server_group_test/integration_test.

An availability probe must observe the port exactly as a fresh server
bind would, so it must not set SO_REUSEADDR. Without it, an occupied port
is correctly rejected and PickAvailablePort() retries another random
port. Verified with a deterministic repro (occupied 127.0.0.1:P; probe
with SO_REUSEADDR reports free, without it reports occupied) and by
stress-running the four port-grabbing rpc tests in parallel.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@chen3feng
chen3feng merged commit 81386ff into master Jul 3, 2026
14 of 15 checks passed
@chen3feng
chen3feng deleted the fix/port-probe-so-reuseaddr branch July 3, 2026 02:47
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.

1 participant