fix: close connection when dial setup fails to avoid a file descriptor leak - #1934
fix: close connection when dial setup fails to avoid a file descriptor leak#1934knQzx wants to merge 1 commit into
Conversation
…r leak Signed-off-by: knQzx <75641500+knQzx@users.noreply.github.com>
| @@ -44,6 +41,15 @@ func dial(ctx context.Context, addr string, num int, opt *Options) (*connect, er | |||
| return nil, err | |||
There was a problem hiding this comment.
💡 Nit — dial-error return still leaks if a custom DialContext returns both a conn and an error
This return sits above the new defer, so a user-supplied opt.DialContext that returns a non-nil net.Conn alongside a non-nil error still leaks the fd — the exact failure mode this PR closes everywhere else in the function.
Stdlib dialers never do this, so it's defensive only, but it's two lines and it makes the guarantee unconditional.
| return nil, err | |
| if conn != nil { | |
| _ = conn.Close() | |
| } | |
| return nil, err |
🤖 Claude reviewCloses the freshly dialed socket when a post-dial setup step (compression validation, JWT fetch, handshake, addendum) fails in I traced every return between the new One follow-up, not a blocker:
Blind spots:
Verdict: ✅ Approve General findings
Inline comments are attached to the relevant lines. This summary updates in place on re-review. |
Summary
dialopens the TCP connection first, then runs the compression / JWT / handshake / addendum setup. if any of those steps fails it returns the error but never closes the socket, so the fd leaks on every failed connection attempt - a reconnect storm against a wrong password, a TLS failure or an unreachable server eventually exhausts the process file descriptors and no new sockets can be openedreproduce: point a client at an endpoint that accepts the TCP connection but fails the handshake (or just use a wrong password), open connections in a loop and watch the open fd count climb without bound. the added
TestDialClosesConnectionOnSetupFailureinjects a connection whose handshake fails and assertsdialclosed it - it fails onmainand passes with this changethe fix closes the freshly dialed connection on any error after the dial succeeds, with a deferred conditional close on the named error return
Checklist