Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server may not be exiting correctly after receiving exit notification #399

Open
siegel opened this issue Oct 10, 2023 · 4 comments · May be fixed by #428 or tower-lsp/tower-lsp#14
Open

Server may not be exiting correctly after receiving exit notification #399

siegel opened this issue Oct 10, 2023 · 4 comments · May be fixed by #428 or tower-lsp/tower-lsp#14
Assignees
Labels
bug Something isn't working

Comments

@siegel
Copy link

siegel commented Oct 10, 2023

This issue describes a symptom in which a language server does not appear to be exiting when it receives the exit protocol notification.

From this comment:

In theory, Server::serve() should already gracefully shut down when it receives an exit message, regardless of the state of stdin, but if it doesn't, then there must be a bug in the logic somewhere.

Creating this issue as requested. :-)

@nayeemrmn
Copy link

It looks like the Deno LSP with VSCode has been leaving old processes alive whenever it gets restarted. This is higher priority for us now.

@ebkalderon Is there a workaround for this, like a way to react to the exit notification to cancel a token around Server::serve()?
https://github.com/denoland/deno/blob/v1.37.2/cli/lsp/mod.rs#L84

@ebkalderon
Copy link
Owner

That certainly doesn't sound good! Unfortunately, I don't think there's currently a user-facing way to directly react to the exit notification yet, looking at the macro-generated code for the exit notification for reference (see the lib.rs module in the tower-lsp-macros crate).

With that said, I'll be sure to prioritize this for investigation tonight. Would you or someone on the Deno team happen to have a minimal reproducible example in mind that can be debugged or treated against? I will later pull a form of it into the tower-lsp repo and turn it into a unit or integration test for the sake of coverage.

Thanks for the patience, folks! Please let me know and I'll start debugging later tonight, in the hopes of pushing out an emergency release soon after.

@nayeemrmn
Copy link

#[tokio::main]
async fn main() {
  use tower_lsp::LanguageServer;
  use tower_lsp::LspService;
  use tower_lsp::Server;
  use tower_lsp::async_trait;
  use tower_lsp::jsonrpc::Result;
  use tower_lsp::lsp_types::InitializeParams;
  use tower_lsp::lsp_types::InitializeResult;

  struct Backend;
  #[async_trait]
  impl LanguageServer for Backend {
    async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> {
        Ok(InitializeResult::default())
    }

    async fn shutdown(&self) -> Result<()> {
        Ok(())
    }
  }

  let stdin = tokio::io::stdin();
  let stdout = tokio::io::stdout();
  let (service, socket) = LspService::new(|_| Backend);
  Server::new(stdin, stdout, socket).serve(service).await;
}

And then run on the CLI:

(printf 'Content-Length: 33\r\n\r\n{"jsonrpc":"2.0","method":"exit"}' && cat) | cargo run

The program will hang until you press Ctrl+D to close stdin.

Any similar hanging stream would do for an automated test.

By the way, I think the main doc comment example (as rendered -- without the hidden lines) at https://github.com/ebkalderon/tower-lsp/blob/v0.20.0/src/lib.rs#L57-L73 will exhibit this.

@jfly
Copy link

jfly commented Oct 25, 2024

@ebkalderon, did you ever figure this out?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
4 participants