internal/lsp/debug: splice in updated servers rather than overwrite

Updating server info was racing with rendering debug templates, because
the state mutex only guards the servers slice, not the values contained
in that slice.

Switch to splicing in updated server data, rather than updating
in-place, to avoid the race.

Change-Id: Ia69895b49cf3f961c58db8e6512ce8b1f5911fd3
Reviewed-on: https://go-review.googlesource.com/c/tools/+/314169
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: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/debug/serve.go b/internal/lsp/debug/serve.go
index 9d55b28..58e59b5 100644
--- a/internal/lsp/debug/serve.go
+++ b/internal/lsp/debug/serve.go
@@ -221,9 +221,14 @@
 func (st *State) updateServer(server *Server) {
 	st.mu.Lock()
 	defer st.mu.Unlock()
-	for _, existing := range st.servers {
+	for i, existing := range st.servers {
 		if existing.ID == server.ID {
-			*existing = *server
+			// Replace, rather than mutate, to avoid a race.
+			newServers := make([]*Server, len(st.servers))
+			copy(newServers, st.servers[:i])
+			newServers[i] = server
+			copy(newServers[i+1:], st.servers[i+1:])
+			st.servers = newServers
 			return
 		}
 	}