Skip to content

Commit fc6b03c

Browse files
authored
Handle requests received after shutdown message (#16262)
## Summary This PR should help in astral-sh/ruff-vscode#676. There are two issues that this is trying to fix all related to the way shutdown should happen as per the protocol: 1. After the server handled the [shutdown request](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#shutdown) and while waiting for the exit notification: > If a server receives requests after a shutdown request those requests should error with `InvalidRequest`. But, we raised an error and exited. This PR fixes it by entering a loop which responds to any request during this period with `InvalidRequest` 2. If the server received an [exit notification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#exit) but the shutdown request was never received, the server handled that by logging and exiting with success but as per the spec: > The server should exit with success code 0 if the shutdown request has been received before; otherwise with error code 1. So, this PR fixes that as well by raising an error in this case. ## Test Plan I'm not sure how to go about testing this without using a mock server.
1 parent fb09d63 commit fc6b03c

File tree

1 file changed

+29
-8
lines changed

1 file changed

+29
-8
lines changed

crates/ruff_server/src/server/connection.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,40 @@ impl Connection {
9191
self.sender
9292
.send(lsp::Response::new_ok(id.clone(), ()).into())?;
9393
tracing::info!("Shutdown request received. Waiting for an exit notification...");
94-
match self.receiver.recv_timeout(std::time::Duration::from_secs(30))? {
95-
lsp::Message::Notification(lsp::Notification { method, .. }) if method == lsp_types::notification::Exit::METHOD => {
96-
tracing::info!("Exit notification received. Server shutting down...");
97-
Ok(true)
98-
},
99-
message => anyhow::bail!("Server received unexpected message {message:?} while waiting for exit notification")
94+
95+
loop {
96+
match &self
97+
.receiver
98+
.recv_timeout(std::time::Duration::from_secs(30))?
99+
{
100+
lsp::Message::Notification(lsp::Notification { method, .. })
101+
if method == lsp_types::notification::Exit::METHOD =>
102+
{
103+
tracing::info!("Exit notification received. Server shutting down...");
104+
return Ok(true);
105+
}
106+
lsp::Message::Request(lsp::Request { id, method, .. }) => {
107+
tracing::warn!(
108+
"Server received unexpected request {method} ({id}) while waiting for exit notification",
109+
);
110+
self.sender.send(lsp::Message::Response(lsp::Response::new_err(
111+
id.clone(),
112+
lsp::ErrorCode::InvalidRequest as i32,
113+
"Server received unexpected request while waiting for exit notification".to_string(),
114+
)))?;
115+
}
116+
message => {
117+
tracing::warn!(
118+
"Server received unexpected message while waiting for exit notification: {message:?}"
119+
);
120+
}
121+
}
100122
}
101123
}
102124
lsp::Message::Notification(lsp::Notification { method, .. })
103125
if method == lsp_types::notification::Exit::METHOD =>
104126
{
105-
tracing::error!("Server received an exit notification before a shutdown request was sent. Exiting...");
106-
Ok(true)
127+
anyhow::bail!("Server received an exit notification before a shutdown request was sent. Exiting...");
107128
}
108129
_ => Ok(false),
109130
}

0 commit comments

Comments
 (0)