From 0c89f898b7b7670a9187bb5102f02435b236d7fa Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 25 Jun 2021 11:49:46 -0400 Subject: [PATCH] internal/jsonrpc2_v2: initialize async before binding The lsprpc package needs to wait on the newly bound connection to perform some tear-down, so it must be safe to call conn.Wait from Bind. Achieve this by switching async from an init pattern to a constructor. This means moving async fields to pointers, but since they weren't safe to use prior to initialization anyway this feels correct. Change-Id: I4f93980915e0b568fbf2db3cd7d062adf06e4b99 Reviewed-on: https://go-review.googlesource.com/c/tools/+/330929 Trust: Robert Findley Run-TryBot: Robert Findley gopls-CI: kokoro TryBot-Result: Go Bot Reviewed-by: Ian Cottrell --- internal/jsonrpc2/conn.go | 4 ++-- internal/jsonrpc2/jsonrpc2.go | 4 +++- internal/jsonrpc2/serve.go | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/jsonrpc2/conn.go b/internal/jsonrpc2/conn.go index 8cf7e81..b7ebc68 100644 --- a/internal/jsonrpc2/conn.go +++ b/internal/jsonrpc2/conn.go @@ -50,7 +50,7 @@ type Connection struct { writerBox chan Writer outgoingBox chan map[ID]chan<- *Response incomingBox chan map[ID]*incoming - async async + async *async } type AsyncCall struct { @@ -87,6 +87,7 @@ func newConnection(ctx context.Context, rwc io.ReadWriteCloser, binder Binder) ( writerBox: make(chan Writer, 1), outgoingBox: make(chan map[ID]chan<- *Response, 1), incomingBox: make(chan map[ID]*incoming, 1), + async: newAsync(), } options, err := binder.Bind(ctx, c) @@ -104,7 +105,6 @@ func newConnection(ctx context.Context, rwc io.ReadWriteCloser, binder Binder) ( } c.outgoingBox <- make(map[ID]chan<- *Response) c.incomingBox <- make(map[ID]*incoming) - c.async.init() // the goroutines started here will continue until the underlying stream is closed reader := options.Framer.Reader(rwc) readToQueue := make(chan *incoming) diff --git a/internal/jsonrpc2/jsonrpc2.go b/internal/jsonrpc2/jsonrpc2.go index 66bd5a3..8f5f040 100644 --- a/internal/jsonrpc2/jsonrpc2.go +++ b/internal/jsonrpc2/jsonrpc2.go @@ -64,10 +64,12 @@ type async struct { errBox chan error } -func (a *async) init() { +func newAsync() *async { + var a async a.ready = make(chan struct{}) a.errBox = make(chan error, 1) a.errBox <- nil + return &a } func (a *async) done() { diff --git a/internal/jsonrpc2/serve.go b/internal/jsonrpc2/serve.go index 04a6be5..c7836b3 100644 --- a/internal/jsonrpc2/serve.go +++ b/internal/jsonrpc2/serve.go @@ -42,7 +42,7 @@ type Dialer interface { type Server struct { listener Listener binder Binder - async async + async *async } // Dial uses the dialer to make a new connection, wraps the returned @@ -68,8 +68,8 @@ func Serve(ctx context.Context, listener Listener, binder Binder) (*Server, erro server := &Server{ listener: listener, binder: binder, + async: newAsync(), } - server.async.init() go server.run(ctx) return server, nil }