From 8d815e365cd2cda2e865dd2e272ebb5a3d4b8772 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 20 Jun 2019 08:36:27 +0200 Subject: [PATCH] rpc: fix rare deadlock when canceling HTTP call context (#19715) When cancelling the context for a call on a HTTP-based client while the call is running, the select in requestOp.wait may hit the <-context.Done() case instead of the <-op.resp case. This doesn't happen often -- our cancel test hasn't caught this even though it ran thousands of times on CI since the RPC client was added. Fixes #19714 --- rpc/client.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rpc/client.go b/rpc/client.go index 02029dc8f6..16511747fa 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -137,9 +137,11 @@ func (op *requestOp) wait(ctx context.Context, c *Client) (*jsonrpcMessage, erro select { case <-ctx.Done(): // Send the timeout to dispatch so it can remove the request IDs. - select { - case c.reqTimeout <- op: - case <-c.closing: + if !c.isHTTP { + select { + case c.reqTimeout <- op: + case <-c.closing: + } } return nil, ctx.Err() case resp := <-op.resp: