about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-09 11:59:04 +0000
committerbors <bors@rust-lang.org>2024-05-09 11:59:04 +0000
commit48bcef3a32dcc87a22200d0cf2be87288a231b38 (patch)
treec53e3ea125e938d6c03734da095f1be6a765d95f
parent85b17d4e11a2690c6546705f9136a99d293ad0b5 (diff)
parenta3ed9fe95506529494895f71321c5332583ad2ba (diff)
downloadrust-48bcef3a32dcc87a22200d0cf2be87288a231b38.tar.gz
rust-48bcef3a32dcc87a22200d0cf2be87288a231b38.zip
Auto merge of #17208 - Wilfred:log_error_from_threads, r=Veykril
fix: Report both IO errors and main_loop errors

If rust-analyzer receives a malformed LSP request, the IO thread terminates with a meaningful error, but then closes the channel.

Once the channel has closed, the main_loop also terminates, but it only has RecvError and can't show a meaningful error. As a result, rust-analyzer would incorrectly claim that the client forgot to shutdown.

```
$ buggy_lsp_client | rust-analyzer
Error: client exited without proper shutdown sequence
```

Instead, include both error messages when the server shuts down.
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs10
1 files changed, 8 insertions, 2 deletions
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
index 78920f3abac..9daae914d79 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
@@ -259,9 +259,15 @@ fn run_server() -> anyhow::Result<()> {
         config.rediscover_workspaces();
     }
 
-    rust_analyzer::main_loop(config, connection)?;
+    // If the io_threads have an error, there's usually an error on the main
+    // loop too because the channels are closed. Ensure we report both errors.
+    match (rust_analyzer::main_loop(config, connection), io_threads.join()) {
+        (Err(loop_e), Err(join_e)) => anyhow::bail!("{loop_e}\n{join_e}"),
+        (Ok(_), Err(join_e)) => anyhow::bail!("{join_e}"),
+        (Err(loop_e), Ok(_)) => anyhow::bail!("{loop_e}"),
+        (Ok(_), Ok(_)) => {}
+    }
 
-    io_threads.join()?;
     tracing::info!("server did shut down");
     Ok(())
 }