-
Notifications
You must be signed in to change notification settings - Fork 259
Description
🟡 medium - bug
File: cmd/root/flags.go (line 152)
Code
func listenAndCloseOnCancel(ctx context.Context, addr string) (net.Listener, error) {
ln, err := server.Listen(ctx, addr)
if err != nil {
return nil, fmt.Errorf("failed to listen on %s: %w", addr, err)
}
go func() {
<-ctx.Done()
_ = ln.Close()
}()
return ln, nil
}Problem
The goroutine started by listenAndCloseOnCancel waits indefinitely for ctx.Done(). If the ctx is never cancelled, this goroutine will never exit, leading to a goroutine leak. While in the current usage (e.g., api.go, mcp.go), the s.Serve or mcp.StartHTTPServer functions are expected to block until the context is cancelled, there's no guarantee that the context will always be cancelled in all possible execution paths or future usages of this function.
Suggested Fix
Add a defer ln.Close() in listenAndCloseOnCancel immediately after server.Listen returns successfully. This ensures the listener is always closed, regardless of whether the context is cancelled or the goroutine runs to completion. The existing goroutine for context cancellation can remain for graceful shutdown, but the defer guarantees resource release in other scenarios.
Found by nightly codebase scan