1
0
Fork 0
mirror of https://github.com/sourcegraph/jsonrpc2.git synced 2026-08-16 10:08:12 +02:00

fix/conn: prevent re-entrant logger deadlock (#99)

Protocol errors invoke the configured logger while the connection is shutting down. Calling user code under the connection mutex meant a logger that sends over the same connection could never observe closure and instead deadlocked. Complete teardown before logging so re-entrant calls return ErrClosed.

Amp-Thread-ID: https://ampcode.com/threads/T-019fb774-aef7-75df-8eb3-8888d6835754

Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Keegan Carruthers-Smith 2026-07-31 11:28:47 +02:00 committed by GitHub
parent 28070556df
commit c3088e5c5d
Signed by: GitHub
GPG key ID: B5690EEEBB952194
2 changed files with 43 additions and 6 deletions

17
conn.go
View file

@ -180,24 +180,29 @@ func (c *Conn) SendResponse(ctx context.Context, resp *Response) error {
func (c *Conn) close(cause error) error {
c.mu.Lock()
defer c.mu.Unlock()
if c.closed {
c.mu.Unlock()
return ErrClosed
}
c.closed = true
for _, call := range c.pending {
close(call.done)
}
close(c.disconnect)
c.mu.Unlock()
c.cancelCtx()
err := c.stream.Close()
// The logger may call back into c, so invoke it only after shutdown is
// complete and c.mu is unlocked.
if cause != nil && cause != io.EOF && cause != io.ErrUnexpectedEOF {
c.logger.Printf("jsonrpc2: protocol error: %v\n", cause)
}
close(c.disconnect)
c.cancelCtx()
c.closed = true
return c.stream.Close()
return err
}
func (c *Conn) readMessages(ctx context.Context) {