ci: re-enable gocritic deferInLoop check (#2288)

deferInLoop was disabled in .golangci.yml, so CI could not catch defer
statements added inside for loops. Such defers run only at function exit,
not per iteration, leaking file descriptors, connections, or locks under
load.

Re-enable the check and fix the two existing occurrences in test code
instead of excluding test files:

- inmemory listener test: deferred conn.Close() inside the accept loop;
  move the per-connection handling into a closure so each connection is
  closed when done.
- TestClientManyServers: every server must stay up until the test ends,
  so hoist the defer out of the loop and stop all servers in a single
  deferred loop.

Fixes #2233

Signed-off-by: Y.Horie <u5.horie@gmail.com>
This commit is contained in:
Y.Horie
2026-06-13 12:49:39 +09:00
committed by GitHub
parent eb9bc61c6d
commit 0643f42190
3 changed files with 29 additions and 20 deletions
-1
View File
@@ -47,7 +47,6 @@ linters:
settings: settings:
gocritic: gocritic:
disabled-checks: disabled-checks:
- deferInLoop
- importShadow - importShadow
- sloppyReassign - sloppyReassign
- unnamedResult - unnamedResult
+9 -1
View File
@@ -2943,12 +2943,20 @@ func TestClientHTTPSConcurrent(t *testing.T) {
func TestClientManyServers(t *testing.T) { func TestClientManyServers(t *testing.T) {
t.Parallel() t.Parallel()
servers := make([]*testEchoServer, 0, 10)
addrs := make([]string, 0, 10) addrs := make([]string, 0, 10)
for range 10 { for range 10 {
s := startEchoServer(t, "tcp", "127.0.0.1:") s := startEchoServer(t, "tcp", "127.0.0.1:")
defer s.Stop() servers = append(servers, s)
addrs = append(addrs, s.Addr()) addrs = append(addrs, s.Addr())
} }
// All servers must stay up until the test ends, so stop them with a single
// deferred loop rather than deferring inside the loop above.
defer func() {
for _, s := range servers {
s.Stop()
}
}()
var wg sync.WaitGroup var wg sync.WaitGroup
for i := range 4 { for i := range 4 {
+20 -18
View File
@@ -57,24 +57,26 @@ func TestInmemoryListener(t *testing.T) {
close(serverCh) close(serverCh)
return return
} }
defer conn.Close() func() {
buf := make([]byte, 30) defer conn.Close()
n, err := conn.Read(buf) buf := make([]byte, 30)
if err != nil { n, err := conn.Read(buf)
t.Errorf("unexpected error: %v", err) if err != nil {
} t.Errorf("unexpected error: %v", err)
buf = buf[:n] }
if !bytes.HasPrefix(buf, []byte("request_")) { buf = buf[:n]
t.Errorf("unexpected request prefix %q. Expecting %q", buf, "request_") if !bytes.HasPrefix(buf, []byte("request_")) {
} t.Errorf("unexpected request prefix %q. Expecting %q", buf, "request_")
resp := fmt.Sprintf("response_%s", buf[len("request_"):]) }
n, err = conn.Write([]byte(resp)) resp := fmt.Sprintf("response_%s", buf[len("request_"):])
if err != nil { n, err = conn.Write([]byte(resp))
t.Errorf("unexpected error: %v", err) if err != nil {
} t.Errorf("unexpected error: %v", err)
if n != len(resp) { }
t.Errorf("unexpected number of bytes written: %d. Expecting %d", n, len(resp)) if n != len(resp) {
} t.Errorf("unexpected number of bytes written: %d. Expecting %d", n, len(resp))
}
}()
} }
}() }()