Repository navigation
Conversation
deadPort() returns the local port of a connected socket, and connect() picked that port. On Linux, a later connect() to that port can get the same port as its source port. The socket then connects to itself. The proxy in proxy-stress-errors.test.ts then tunnels to itself, and the test sees ConnectionRefused or Malformed_HTTP_Response, not a 502. The holder now binds 127.0.0.1 (localAddress) before it connects. Linux does not give a port that bind() picked to connect(), so the self-connect cannot occur. The port stays bound, so listen(0) still skips it. Probe, 150000 dials to a dead port on Linux 6.17: before: 11 self-connects after: 0 self-connects The helper keeps the holder's port. It does not return the listener's port, as #35400 does. On Windows, listen(0) hands out the port of a closed listener while its accepted socket is still open: 500 of 20000 listens in a probe, and 0 with this change.
|
Reproduced on Linux with the bun canary, without CI:
The change is in a test helper only. No runtime code changes. CI: build 110054 passed 181 of 182 jobs, on every platform. No
The diff is ready for review. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Essentials Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 10 included reviews per hour; 3 remain after this review. WalkthroughChangesdeadPort connection handling
Merge Risk: ⚪ Minimal · up to The helper now binds its holder socket to loopback to prevent self-connections while retaining the reserved-port behavior. No current merge-blocking risk remains. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
|
Updated 11:28 PM PT - Sep 3rd, 2026
❌ @robobun, your commit 5f9a67e has 1 failures in 🧪 To try this PR locally: bunx bun-pr 41336That installs a local version of the PR into your bun-41336 --bun |
Problem
proxy-stress-errors.test.tsflakes on Linux. The Alpine 3.23 x64 lane failedupstream unreachable via proxy > https-proxy, CONNECT upstream refused → 502withTypeError: Unable to connect. Is the computer able to access the url?(code: "ConnectionRefused"). test(proxy-stress): return deadPort()'s bind(0) port, not the connect-autobound one #35400 sawMalformed_HTTP_Responsefrom the same cause.deadPort()(test/js/bun/http/proxy-stress-helpers.ts:721) returns a port thatconnect()picked. Linux can give that port as the source port to a laterconnect()to the same port. That socket connects to itself. The proxy then tunnels to itself and does not send the 502.Fix
127.0.0.1(localAddress) before it connects.connect()does not pick a port thatbind()holds. The port stays bound, solisten(0)still skips it (the guard from test(proxy-stress): hold deadPort() bound so concurrent listen(0) can't steal it #35269).listen(0)hands out that port while the accepted socket is still open.proxy-stress-errors.test.tspasses 30 of 30 runs. All sevenproxy-stress-*files pass on Linux (release and ASAN) and on Windows x64.Background
connect()to it fails withECONNREFUSED.connect()in__inet_hash_connect. It can reuse a port that anotherconnect()picked, if the 4-tuple is unique. It skips a port thatbind()picked.Notes
Probes: Linux 6.17 (port range 32768 to 60999) and Windows Server 2019, with bun canary.
deadPort()shapelisten(0)collisions (500 held, 20000 listens)listen(0)collisions (500 held, 20000 listens)connect()bind()ConnectionRefusedfor an https target (the inner TLS handshake reads its own ClientHello,src/http/ProxyTunnel.rs:432), andMalformed_HTTP_Responsefor an http target.listen(0)column for main shows little.listen(0)prefers odd ports, andconnect()prefers even ports.listen(0)allocates ports in sequence. So the test(proxy-stress): return deadPort()'s bind(0) port, not the connect-autobound one #35400 collision needs a wrap of the 16384-port range while a test holds the port. That is unlikely, but the port is not reserved.sink.close()in 500 of 500 runs. So the helper does not need to wait for the accept.bind(0)range: one port per dead port, for 60 seconds.bun test test/js/bun/http/proxy-stress-*.test.ts: Linux release 852 pass and 1 skip, Linux ASAN debug build 853 pass, Windows x64 852 pass and 1 skip.proxy-stress-errors.test.tsalone: Linux release 30 of 30, ASAN 3 of 3, Windows 10 of 10.no test proof · iteration 1 · no src or test change; test-proof not applicable