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:
parent
28070556df
commit
c3088e5c5d
2 changed files with 43 additions and 6 deletions
17
conn.go
17
conn.go
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue