Skip to content

Deflake JettyTransporterTest.testGet_HTTP3 (UDP port collision) - #2037

Merged
elharo merged 2 commits into
masterfrom
fix-2036-http3-udp-port
Aug 5, 2026
Merged

Deflake JettyTransporterTest.testGet_HTTP3 (UDP port collision)#2037
elharo merged 2 commits into
masterfrom
fix-2036-http3-udp-port

Conversation

@elharo

@elharo elharo commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #2036

Problem

JettyTransporterTest.testGet_HTTP3 is flaky: binding the HTTP/3 (UDP) connector to the HTTPS TCP connector's port fails with java.net.BindException: Address already in use.

Root cause

The test bound both connectors to the same numeric port by reusing getHttpsPort(), which is an OS-assigned TCP port. TCP and UDP port spaces are allocated independently, so the same-numbered UDP port may already be in use by another process. The collision is inherent to the "let the OS pick a TCP port, then force UDP onto the same number" pattern (verified by experiment: ~1% collision rate with a few hundred UDP sockets occupied).

Fix

  • Added HttpServer.findFreeTcpAndUdpPort(), which probes for a port that is free for both TCP and UDP.
  • Added HttpServer.addHttp2OnlyConnectorWithMutualTLS(int port) so the HTTPS (HTTP/2) connector can be bound to that exact port.
  • testGet_HTTP3 now reserves such a port and binds both connectors to it, keeping the intended "HTTP/2 and HTTP/3 on the same port" semantics.

Verified: JettyTransporterTest (89 tests), ApacheTransporterTest (93), and JdkTransporterTest (92) all pass; the HTTP/3 requests in testGet_HTTP3 are served over HTTP/3.0.

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Clean, well-reasoned fix that correctly identifies the root cause: TCP and UDP port namespaces are independent, so an OS-assigned TCP port may collide with an already-occupied UDP port. The probe-and-retry approach finds a port free in both namespaces.

Observations (non-blocking):

  • The TOCTOU race between the probe closing sockets and connectors binding is inherent to any port-probing approach, and the 20-iteration retry loop makes exhaustion statistically negligible (~10⁻⁴⁰ failure probability at 1% collision rate).
  • The refactoring of addHttp2Connector to accept an optional port parameter is backward-compatible — all existing no-arg callers pass -1 (OS-assigned).
  • Confirmed this is the only place in the codebase that reuses a TCP port number for a UDP binding.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of Guillaume Nodet

@elharo elharo changed the title Fix flaky JettyTransporterTest.testGet_HTTP3 (UDP port collision) Deflake JettyTransporterTest.testGet_HTTP3 (UDP port collision) Aug 5, 2026
@elharo
elharo merged commit 8ea57ef into master Aug 5, 2026
23 checks passed
@elharo
elharo deleted the fix-2036-http3-udp-port branch August 5, 2026 18:17
@github-actions github-actions Bot added this to the 2.0.22 milestone Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

@elharo Please assign appropriate label to PR according to the type of change.

@elharo elharo added maintenance skip-changelog Skip this PR from automatically changelog generation labels Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance skip-changelog Skip this PR from automatically changelog generation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

org.eclipse.aether.transport.jetty.JettyTransporterTest.testGet_HTTP3 is flaky due to timeout

2 participants