Skip to content

Commit

Permalink
gopls/internal/lsp/protocol: deliver log messages in order
Browse files Browse the repository at this point in the history
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 <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
adonovan authored and findleyr committed Jan 17, 2024
1 parent 9164f2a commit d517112
Showing 1 changed file with 23 additions and 3 deletions.
26 changes: 23 additions & 3 deletions gopls/internal/lsp/protocol/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package protocol
import (
"bytes"
"context"
"sync"

"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/core"
Expand Down Expand Up @@ -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
)

0 comments on commit d517112

Please sign in to comment.