gopls/internal/lsp/protocol: deliver log messages in order

This fixes a predicted bug that was noticed while reading
the code.

Fixes golang/go#61216

Change-Id: I9614454fbd8538cb0b9eb1f56f11934cb88a7aed
Reviewed-on: https://go-review.googlesource.com/c/tools/+/555635
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Alan Donovan 2024-01-12 11:50:48 -05:00 коммит произвёл Robert Findley
Родитель 9164f2aedb
Коммит d517112994
1 изменённых файлов: 23 добавлений и 3 удалений

Просмотреть файл

@ -7,6 +7,7 @@ package protocol
import (
"bytes"
"context"
"sync"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/core"
@ -38,8 +39,27 @@ func LogEvent(ctx context.Context, ev core.Event, lm label.Map, mt MessageType)
if event.IsError(ev) {
msg.Type = Error
}
// TODO(adonovan): the goroutine here could cause log
// messages to be delivered out of order! Use a queue.
go client.LogMessage(xcontext.Detach(ctx), msg)
// The background goroutine lives forever once started,
// and ensures log messages are sent in order (#61216).
startLogSenderOnce.Do(func() {
go func() {
for f := range logQueue {
f()
}
}()
})
// Add the log item to a queue, rather than sending a
// window/logMessage request to the client synchronously,
// which would slow down this thread.
ctx2 := xcontext.Detach(ctx)
logQueue <- func() { client.LogMessage(ctx2, msg) }
return ctx
}
var (
startLogSenderOnce sync.Once
logQueue = make(chan func(), 100) // big enough for a large transient burst
)