Skip to content

Commit

Permalink
fix(lsp): force shutdown after a timeout (#21251)
Browse files Browse the repository at this point in the history
  • Loading branch information
nayeemrmn authored and bartlomieju committed Nov 24, 2023
1 parent cffdbe9 commit e7d2648
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
11 changes: 8 additions & 3 deletions cli/lsp/language_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use std::env;
use std::fmt::Write as _;
use std::path::PathBuf;
use std::sync::Arc;
use tokio_util::sync::CancellationToken;
use tower_lsp::jsonrpc::Error as LspError;
use tower_lsp::jsonrpc::Result as LspResult;
use tower_lsp::lsp_types::request::*;
Expand Down Expand Up @@ -156,7 +157,7 @@ impl LspNpmConfigHash {
}

#[derive(Debug, Clone)]
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>);
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>, CancellationToken);

#[derive(Debug)]
pub struct StateNpmSnapshot {
Expand Down Expand Up @@ -226,8 +227,11 @@ pub struct Inner {
}

impl LanguageServer {
pub fn new(client: Client) -> Self {
Self(Arc::new(tokio::sync::RwLock::new(Inner::new(client))))
pub fn new(client: Client, token: CancellationToken) -> Self {
Self(
Arc::new(tokio::sync::RwLock::new(Inner::new(client))),
token,
)
}

/// Similar to `deno cache` on the command line, where modules will be cached
Expand Down Expand Up @@ -3216,6 +3220,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
}

async fn shutdown(&self) -> LspResult<()> {
self.1.cancel();
self.0.write().await.shutdown().await
}

Expand Down
21 changes: 19 additions & 2 deletions cli/lsp/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.

use deno_core::error::AnyError;
use deno_core::unsync::spawn;
use tokio_util::sync::CancellationToken;
use tower_lsp::LspService;
use tower_lsp::Server;

Expand Down Expand Up @@ -39,8 +41,12 @@ pub async fn start() -> Result<(), AnyError> {
let stdin = tokio::io::stdin();
let stdout = tokio::io::stdout();

let token = CancellationToken::new();
let builder = LspService::build(|client| {
language_server::LanguageServer::new(client::Client::from_tower(client))
language_server::LanguageServer::new(
client::Client::from_tower(client),
token.clone(),
)
})
// TODO(nayeemrmn): The extension has replaced this with the `deno.cache`
// command as of vscode_deno 3.21.0 / 2023.09.05. Remove this eventually.
Expand Down Expand Up @@ -81,7 +87,18 @@ pub async fn start() -> Result<(), AnyError> {

let (service, socket) = builder.finish();

Server::new(stdin, stdout, socket).serve(service).await;
// TODO(nayeemrmn): This cancellation token is a workaround for
// https://github.com/denoland/deno/issues/20700. Remove when
// https://github.com/ebkalderon/tower-lsp/issues/399 is fixed.
// Force end the server 8 seconds after receiving a shutdown request.
tokio::select! {
biased;
_ = Server::new(stdin, stdout, socket).serve(service) => {}
_ = spawn(async move {
token.cancelled().await;
tokio::time::sleep(std::time::Duration::from_secs(8)).await;
}) => {}
}

Ok(())
}
6 changes: 4 additions & 2 deletions cli/lsp/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ impl ReplLanguageServer {
super::logging::set_lsp_log_level(log::Level::Debug);
super::logging::set_lsp_warn_level(log::Level::Debug);

let language_server =
super::language_server::LanguageServer::new(Client::new_for_repl());
let language_server = super::language_server::LanguageServer::new(
Client::new_for_repl(),
Default::default(),
);

let cwd_uri = get_cwd_uri()?;

Expand Down

0 comments on commit e7d2648

Please sign in to comment.