Skip to content

Fix ephemeral port leak: pass context to ClientSession.DialStream#373

Merged
0pcom merged 6 commits intoskycoin:developfrom
0pcom:fix/ephemeral-port-leak
Apr 7, 2026
Merged

Fix ephemeral port leak: pass context to ClientSession.DialStream#373
0pcom merged 6 commits intoskycoin:developfrom
0pcom:fix/ephemeral-port-leak

Conversation

@0pcom
Copy link
Copy Markdown
Collaborator

@0pcom 0pcom commented Apr 7, 2026

Summary

  • ClientSession.DialStream now accepts context.Context
  • When context is cancelled, the stream is closed immediately, freeing the reserved ephemeral port
  • Client.DialStream passes its context to all ClientSession.DialStream calls

Root Cause

ClientSession.DialStream didn't accept a context. When the caller's deadline expired (e.g., 30s dial timeout in the setup-node), readResponse kept blocking on the yamux stream read until HandshakeTimeout fired. The ephemeral port reserved by writeRequest stayed allocated the entire time.

With 6 DMSG servers tried sequentially per dial attempt, and many concurrent route setup requests, the ~16K ephemeral port space exhausted within minutes.

Fix

A goroutine watches the context and calls dStr.Close() when cancelled. This interrupts the blocked readResponse, triggers the defer that frees the port, and returns immediately. The port is freed in milliseconds instead of waiting up to HandshakeTimeout.

Test plan

  • Verify setup-node no longer gets "ephemeral port space exhausted" under load
  • Verify normal DMSG stream dials still work
  • CI tests pass

0pcom added 6 commits April 7, 2026 10:58
ClientSession.DialStream didn't accept a context, so when the
caller's deadline expired, the blocked readResponse kept the
ephemeral port reserved until HandshakeTimeout fired (20-30s per
server). With 6 servers tried sequentially, a single failed dial
could hold ports for minutes.

Now DialStream accepts context and spawns a goroutine that closes
the stream when the context is cancelled, immediately interrupting
any blocked read/write and freeing the ephemeral port.

Also: Client.DialStream now passes ctx to all ClientSession.DialStream
calls (phases 0-3) and checks ctx.Err() between phases.
@0pcom 0pcom merged commit e26b298 into skycoin:develop Apr 7, 2026
3 checks passed
@0pcom 0pcom deleted the fix/ephemeral-port-leak branch April 7, 2026 22:53
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