@@ -168,14 +168,15 @@ func (c *Conn) Call(ctx context.Context, method string, params, result interface
168
168
ctx = h .Request (ctx , c , Send , req )
169
169
}
170
170
171
- // we have to add ourselves to the pending map before we send, otherwise we
172
- // are racing the response
173
- rchan := make (chan * WireResponse )
171
+ // We have to add ourselves to the pending map before we send, otherwise we
172
+ // are racing the response. Also add a buffer to rchan, so that if we get a
173
+ // wire response between the time this call is cancelled and id is deleted
174
+ // from c.pending, the send to rchan will not block.
175
+ rchan := make (chan * WireResponse , 1 )
174
176
c .pendingMu .Lock ()
175
177
c .pending [id ] = rchan
176
178
c .pendingMu .Unlock ()
177
179
defer func () {
178
- // clean up the pending response handler on the way out
179
180
c .pendingMu .Lock ()
180
181
delete (c .pending , id )
181
182
c .pendingMu .Unlock ()
@@ -340,22 +341,19 @@ func (c *Conn) Run(ctx context.Context) error {
340
341
}()
341
342
342
343
case msg .ID != nil : // msg.ID not nil, handle the response
343
- // we have a response, get the pending entry from the map
344
+ // If method is not set, this should be a response, in which case we must
345
+ // have an id to send the response back to the caller.
344
346
c .pendingMu .Lock ()
345
- rchan := c .pending [* msg .ID ]
346
- if rchan != nil {
347
- delete (c .pending , * msg .ID )
348
- }
347
+ rchan , ok := c .pending [* msg .ID ]
349
348
c .pendingMu .Unlock ()
350
-
351
- // send the reply to the channel
352
- resp := & WireResponse {
353
- Result : msg .Result ,
354
- Error : msg .Error ,
355
- ID : msg .ID ,
349
+ if ok {
350
+ resp := & WireResponse {
351
+ Result : msg .Result ,
352
+ Error : msg .Error ,
353
+ ID : msg .ID ,
354
+ }
355
+ rchan <- resp
356
356
}
357
- rchan <- resp
358
- close (rchan ) // for rchan range loop
359
357
360
358
default :
361
359
for _ , h := range c .handlers {
@@ -430,9 +428,9 @@ func (r *Request) Reply(ctx context.Context, result interface{}, reqErr error) e
430
428
return err
431
429
}
432
430
resp := & WireResponse {
433
- JSONRPC : Version ,
434
- Result : raw ,
435
- ID : r .ID ,
431
+ // JSONRPC: Version,
432
+ Result : raw ,
433
+ ID : r .ID ,
436
434
}
437
435
if reqErr != nil {
438
436
var callErr * Error
0 commit comments