diff --git a/internal/jsonrpc2/jsonrpc2.go b/internal/jsonrpc2/jsonrpc2.go index 8dd0bd91deb..8e651aa2dfe 100644 --- a/internal/jsonrpc2/jsonrpc2.go +++ b/internal/jsonrpc2/jsonrpc2.go @@ -386,8 +386,10 @@ func (c *Conn) Run(runCtx context.Context) error { Error: msg.Error, ID: msg.ID, } - rchan <- response - close(rchan) + if rchan != nil { + rchan <- response + close(rchan) + } default: for _, h := range c.handlers { h.Error(runCtx, fmt.Errorf("message not a call, notify or response, ignoring")) diff --git a/internal/jsonrpc2/jsonrpc2_test.go b/internal/jsonrpc2/jsonrpc2_test.go index 89252fd10fa..42df44c41f2 100644 --- a/internal/jsonrpc2/jsonrpc2_test.go +++ b/internal/jsonrpc2/jsonrpc2_test.go @@ -92,6 +92,32 @@ func TestHeaderCall(t *testing.T) { } } +func TestResultsNoPendingID(t *testing.T) { + ctx := context.Background() + result := `{"jsonrpc":"2.0","result":["test"],"id":1}` + + aR, bW := io.Pipe() + bR, aW := io.Pipe() + + stream := jsonrpc2.NewStream(aR, aW) + run(ctx, t, false, bR, bW) + + ch := make(chan int) + + go func() { + stream.Write(ctx, []byte(result)) + stream.Write(ctx, []byte(result)) + + ch <- 0 + }() + + select { + case <-ch: + case <-time.After(time.Second * 1): + t.Fatalf("NoPendingID Blocking") + } +} + func prepare(ctx context.Context, t *testing.T, withHeaders bool) (*jsonrpc2.Conn, *jsonrpc2.Conn) { aR, bW := io.Pipe() bR, aW := io.Pipe()