mirror of
https://github.com/c-cube/linol.git
synced 2025-12-09 20:55:43 -05:00
[#22] Threat shutdown and exit requests correctly
Problem: As in [#22], we want to shut down our LSP server correctly. That means we should close the pipe and end process after an exit request. This require proper `shutdown : unit -> bool` function passed to `Jsonrpc2.Make.run` which returns `true` after the server received an exit request. Right now both exit and shutdown requests are setting LSP server's internal var `_quit` to true. It's very intuitive to use this var in `shutdown`, but we can't do it, since in this case the server would stop receiving new messages right after the shutdown request, despite the fact according to the LSP specification it had to wait the exit request. Solution: Instead of `_quit : bool` use ``` status : [ `Running | `ReceivedShutdown | `ReceivedExit ] ``` and suggest ``` shutdown () = s#get_status = `ReceivedExit ``` in docs for `Jsonrpc2.Make.run` and in the templete/example.
This commit is contained in:
parent
c6969ab87c
commit
09311ae258
3 changed files with 17 additions and 5 deletions
|
|
@ -81,7 +81,10 @@ class lsp_server =
|
|||
let run () =
|
||||
let s = new lsp_server in
|
||||
let server = Linol_lwt.Jsonrpc2.create_stdio s in
|
||||
let task = Linol_lwt.Jsonrpc2.run server in
|
||||
let task =
|
||||
let shutdown () = s#get_status = `ReceivedExit in
|
||||
Linol_lwt.Jsonrpc2.run ~shutdown server
|
||||
in
|
||||
match Linol_lwt.run task with
|
||||
| () -> ()
|
||||
| exception e ->
|
||||
|
|
|
|||
|
|
@ -302,6 +302,10 @@ module Make (IO : IO) : S with module IO = IO = struct
|
|||
IO.return
|
||||
@@ Error (E (ErrorCode.InvalidRequest, "content-type must be 'utf-8'"))
|
||||
|
||||
(** [shutdown ()] is called after processing each request to check if the server
|
||||
could wait for new messages.
|
||||
When launching an LSP server using [Server.Make.server], the
|
||||
natural choice for it is [s#get_status = `ReceivedExit] *)
|
||||
let run ?(shutdown = fun _ -> false) (self : t) : unit IO.t =
|
||||
let process_msg r =
|
||||
let module M = Jsonrpc.Packet in
|
||||
|
|
|
|||
|
|
@ -157,9 +157,14 @@ module Make (IO : IO) = struct
|
|||
class virtual server =
|
||||
object (self)
|
||||
inherit base_server
|
||||
val mutable _quit = false
|
||||
|
||||
val mutable status : [ `Running | `ReceivedShutdown | `ReceivedExit ] =
|
||||
`Running
|
||||
|
||||
val docs : (DocumentUri.t, doc_state) Hashtbl.t = Hashtbl.create 16
|
||||
method! must_quit = _quit
|
||||
method get_status = status
|
||||
(** Check if exit or shutdown request was made by the client.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
method find_doc (uri : DocumentUri.t) : doc_state option =
|
||||
try Some (Hashtbl.find docs uri) with Not_found -> None
|
||||
|
|
@ -313,7 +318,7 @@ module Make (IO : IO) = struct
|
|||
match r with
|
||||
| Lsp.Client_request.Shutdown ->
|
||||
Log.info (fun k -> k "shutdown");
|
||||
_quit <- true;
|
||||
status <- `ReceivedShutdown;
|
||||
IO.return ()
|
||||
| Lsp.Client_request.Initialize i ->
|
||||
Log.debug (fun k -> k "req: initialize");
|
||||
|
|
@ -583,7 +588,7 @@ module Make (IO : IO) = struct
|
|||
~old_content:(Lsp.Text_document.text old_doc)
|
||||
~new_content:new_st.content
|
||||
| Lsp.Client_notification.Exit ->
|
||||
_quit <- true;
|
||||
status <- `ReceivedExit;
|
||||
IO.return ()
|
||||
| Lsp.Client_notification.DidSaveTextDocument _
|
||||
| Lsp.Client_notification.WillSaveTextDocument _
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue