Shutdown language servers better (#35038)

Follow-up of https://github.com/zed-industries/zed/pull/33417

* adjust prettier mock LSP to handle `shutdown` and `exit` messages
* removed another `?.log_err()` backtrace from logs and improved the
logging info
* always handle the last parts of the shutdown logic even if the
shutdown response had failed

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-07-24 18:24:53 +03:00 committed by GitHub
parent 2a9355a3d2
commit 2658b2801e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 27 deletions

View file

@ -877,39 +877,41 @@ impl LanguageServer {
let server = self.server.clone(); let server = self.server.clone();
let name = self.name.clone(); let name = self.name.clone();
let server_id = self.server_id;
let mut timer = self.executor.timer(SERVER_SHUTDOWN_TIMEOUT).fuse(); let mut timer = self.executor.timer(SERVER_SHUTDOWN_TIMEOUT).fuse();
Some( Some(async move {
async move { log::debug!("language server shutdown started");
log::debug!("language server shutdown started");
select! { select! {
request_result = shutdown_request.fuse() => { request_result = shutdown_request.fuse() => {
match request_result { match request_result {
ConnectionResult::Timeout => { ConnectionResult::Timeout => {
log::warn!("timeout waiting for language server {name} to shutdown"); log::warn!("timeout waiting for language server {name} (id {server_id}) to shutdown");
}, },
ConnectionResult::ConnectionReset => {}, ConnectionResult::ConnectionReset => {
ConnectionResult::Result(r) => r?, log::warn!("language server {name} (id {server_id}) closed the shutdown request connection");
} },
ConnectionResult::Result(Err(e)) => {
log::error!("Shutdown request failure, server {name} (id {server_id}): {e:#}");
},
ConnectionResult::Result(Ok(())) => {}
} }
_ = timer => {
log::info!("timeout waiting for language server {name} to shutdown");
},
} }
response_handlers.lock().take(); _ = timer => {
Self::notify_internal::<notification::Exit>(&outbound_tx, &()).ok(); log::info!("timeout waiting for language server {name} (id {server_id}) to shutdown");
outbound_tx.close(); },
output_done.recv().await;
server.lock().take().map(|mut child| child.kill());
log::debug!("language server shutdown finished");
drop(tasks);
anyhow::Ok(())
} }
.log_err(),
) response_handlers.lock().take();
Self::notify_internal::<notification::Exit>(&outbound_tx, &()).ok();
outbound_tx.close();
output_done.recv().await;
server.lock().take().map(|mut child| child.kill());
drop(tasks);
log::debug!("language server shutdown finished");
Some(())
})
} else { } else {
None None
} }

View file

@ -152,6 +152,10 @@ async function handleMessage(message, prettier) {
throw new Error(`Message method is undefined: ${JSON.stringify(message)}`); throw new Error(`Message method is undefined: ${JSON.stringify(message)}`);
} else if (method == "initialized") { } else if (method == "initialized") {
return; return;
} else if (method === "shutdown") {
sendResponse({ result: {} });
} else if (method == "exit") {
process.exit(0);
} }
if (id === undefined) { if (id === undefined) {