Bug Description
Abort() in internal/mcp/client.go (lines 375-401) reads c.wsConn, c.stdin, c.cmd, c.procCancel without holding c.mu. The comment acknowledges this is intentional to avoid deadlock when called from sendRequest's cancel path (which already holds c.mu), but Abort() is also called from Close() (line 328) which does not hold c.mu.
Meanwhile, Start() (lines 129, 165-168) writes these same fields without holding c.mu. If Close() and Start() are called concurrently on the same Client instance, Abort() reads these fields without synchronization while Start() writes them — a data race.
Trigger Scenario
- Goroutine A calls
Client.Close() → Abort() reads fields without c.mu
- Goroutine B calls
Client.Start() → writes fields without c.mu
- Data race —
go test -race would flag it
Severity
Medium — requires concurrent Close()+Start() on the same Client.
Fix Suggestion
In Abort(), for the Close() call path, acquire c.mu before reading the fields. For the sendRequest cancel path (already holds c.mu), skip the lock.
File
internal/mcp/client.go, lines 375-401, 325-343, 113-168
Bug Description
Abort()ininternal/mcp/client.go(lines 375-401) readsc.wsConn,c.stdin,c.cmd,c.procCancelwithout holdingc.mu. The comment acknowledges this is intentional to avoid deadlock when called fromsendRequest's cancel path (which already holdsc.mu), butAbort()is also called fromClose()(line 328) which does not holdc.mu.Meanwhile,
Start()(lines 129, 165-168) writes these same fields without holdingc.mu. IfClose()andStart()are called concurrently on the sameClientinstance,Abort()reads these fields without synchronization whileStart()writes them — a data race.Trigger Scenario
Client.Close()→Abort()reads fields withoutc.muClient.Start()→ writes fields withoutc.mugo test -racewould flag itSeverity
Medium — requires concurrent
Close()+Start()on the sameClient.Fix Suggestion
In
Abort(), for theClose()call path, acquirec.mubefore reading the fields. For thesendRequestcancel path (already holdsc.mu), skip the lock.File
internal/mcp/client.go, lines 375-401, 325-343, 113-168