@@ -61,6 +61,17 @@ func Serve(
6161 logger .Info ("starting LSP server" )
6262
6363 conn := jsonrpc2 .NewConn (stream )
64+ // connCtx is a context scoped to the connection's lifetime. It is cancelled
65+ // when the connection is done (or when ctx is cancelled), so that background
66+ // goroutines (e.g. RunChecks) do not outlive the connection.
67+ connCtx , connCancel := context .WithCancel (context .Background ())
68+ go func () {
69+ select {
70+ case <- ctx .Done ():
71+ case <- conn .Done ():
72+ }
73+ connCancel ()
74+ }()
6475 lsp := & lsp {
6576 conn : conn ,
6677 client : protocol .ClientDispatcher (
@@ -76,6 +87,8 @@ func Serve(
7687 queryExecutor : queryExecutor ,
7788 opener : source .NewMap (nil ),
7889 irSession : new (ir.Session ),
90+ connCtx : connCtx ,
91+ connCancel : connCancel ,
7992 }
8093 lsp .fileManager = newFileManager (lsp )
8194 lsp .workspaceManager = newWorkspaceManager (lsp )
@@ -100,9 +113,11 @@ func Serve(
100113// Its handler methods are not defined in buflsp.go; they are defined in other files, grouped
101114// according to the groupings in
102115type lsp struct {
103- conn jsonrpc2.Conn
104- client protocol.Client
105- container appext.Container
116+ conn jsonrpc2.Conn
117+ client protocol.Client
118+ container appext.Container
119+ connCtx context.Context // cancelled when the connection is done
120+ connCancel context.CancelFunc // cancels connCtx
106121
107122 logger * slog.Logger
108123 bufVersion string // buf version, set at server creation
@@ -150,7 +165,10 @@ func (l *lsp) newHandler() (jsonrpc2.Handler, error) {
150165 return nil , err
151166 }
152167 actual := protocol .ServerHandler (server , nil )
153- return jsonrpc2 .AsyncHandler (func (ctx context.Context , reply jsonrpc2.Replier , req jsonrpc2.Request ) error {
168+ // [protocol.CancelHandler] intercepts $/cancelRequest notifications from the client and
169+ // cancels the context of the matching in-flight request. It must wrap AsyncHandler so
170+ // that the cancellable context is the one running inside each spawned goroutine.
171+ return protocol .CancelHandler (jsonrpc2 .AsyncHandler (func (ctx context.Context , reply jsonrpc2.Replier , req jsonrpc2.Request ) error {
154172 l .logger .Debug (
155173 "handling request" ,
156174 slog .String ("method" , req .Method ()),
@@ -181,5 +199,5 @@ func (l *lsp) newHandler() (jsonrpc2.Handler, error) {
181199 )
182200 }
183201 return nil
184- }), nil
202+ })) , nil
185203}
0 commit comments