fix(lsp): non-blocking response dispatch to avoid client deadlock

readLoop sent the response on the pending channel while holding c.mu. A misbehaving server sending a duplicate response for the same id would block on the buffered(1) channel under the lock, deadlocking all future dispatches. Use a non-blocking send (matching the notification path).
This commit is contained in:
2026-06-20 00:33:33 +01:00
parent 61b04b46cd
commit 80c3f03f62
+8 -1
View File
@@ -321,7 +321,14 @@ func (c *Client) readLoop() {
if err := json.Unmarshal(body, &resp); err == nil && resp.ID != 0 {
c.mu.Lock()
if ch, ok := c.pending[resp.ID]; ok {
ch <- &resp
// Non-blocking send: the pending channel is buffered(1) and read
// exactly once. A misbehaving server that sends a duplicate
// response for the same id must not block here while holding c.mu
// (which would deadlock all future dispatches).
select {
case ch <- &resp:
default:
}
}
c.mu.Unlock()
continue