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 <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/jsonrpc2_v2/conn.go b/internal/jsonrpc2_v2/conn.go
index 6d92c0c..7d99a02 100644
--- a/internal/jsonrpc2_v2/conn.go
+++ b/internal/jsonrpc2_v2/conn.go
@@ -50,7 +50,7 @@
 	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 @@
 		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 @@
 	}
 	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_v2/jsonrpc2.go b/internal/jsonrpc2_v2/jsonrpc2.go
index 4e853d5..faaf205 100644
--- a/internal/jsonrpc2_v2/jsonrpc2.go
+++ b/internal/jsonrpc2_v2/jsonrpc2.go
@@ -64,10 +64,12 @@
 	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_v2/serve.go b/internal/jsonrpc2_v2/serve.go
index f3b78f5..98e8894 100644
--- a/internal/jsonrpc2_v2/serve.go
+++ b/internal/jsonrpc2_v2/serve.go
@@ -42,7 +42,7 @@
 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 @@
 	server := &Server{
 		listener: listener,
 		binder:   binder,
+		async:    newAsync(),
 	}
-	server.async.init()
 	go server.run(ctx)
 	return server, nil
 }