Skip to content

Commit acafce3

Browse files
committed
Auto merge of rust-lang#16309 - Veykril:proc-macro-srv-err, r=Veykril
Recognize proc macro server unexpectedly exiting and report the exit code
2 parents c246ecf + 21a953f commit acafce3

File tree

3 files changed

+52
-12
lines changed

3 files changed

+52
-12
lines changed

crates/proc-macro-api/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ mod version;
1414
use indexmap::IndexSet;
1515
use paths::AbsPathBuf;
1616
use span::Span;
17-
use std::{fmt, io, sync::Mutex};
18-
use triomphe::Arc;
17+
use std::{
18+
fmt, io,
19+
sync::{Arc, Mutex},
20+
};
1921

2022
use serde::{Deserialize, Serialize};
2123

@@ -81,9 +83,11 @@ impl PartialEq for ProcMacro {
8183
}
8284
}
8385

86+
#[derive(Clone, Debug)]
8487
pub struct ServerError {
8588
pub message: String,
86-
pub io: Option<io::Error>,
89+
// io::Error isn't Clone for some reason
90+
pub io: Option<Arc<io::Error>>,
8791
}
8892

8993
impl fmt::Display for ServerError {

crates/proc-macro-api/src/process.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! Handle process life-time and message passing for proc-macro client
22
33
use std::{
4-
io::{self, BufRead, BufReader, Write},
4+
io::{self, BufRead, BufReader, Read, Write},
55
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
6+
sync::Arc,
67
};
78

89
use paths::{AbsPath, AbsPathBuf};
@@ -15,9 +16,11 @@ use crate::{
1516

1617
#[derive(Debug)]
1718
pub(crate) struct ProcMacroProcessSrv {
18-
_process: Process,
19+
process: Process,
1920
stdin: ChildStdin,
2021
stdout: BufReader<ChildStdout>,
22+
/// Populated when the server exits.
23+
server_exited: Option<ServerError>,
2124
version: u32,
2225
mode: SpanMode,
2326
}
@@ -29,9 +32,10 @@ impl ProcMacroProcessSrv {
2932
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
3033

3134
io::Result::Ok(ProcMacroProcessSrv {
32-
_process: process,
35+
process,
3336
stdin,
3437
stdout,
38+
server_exited: None,
3539
version: 0,
3640
mode: SpanMode::Id,
3741
})
@@ -105,8 +109,35 @@ impl ProcMacroProcessSrv {
105109
}
106110

107111
pub(crate) fn send_task(&mut self, req: Request) -> Result<Response, ServerError> {
112+
if let Some(server_error) = &self.server_exited {
113+
return Err(server_error.clone());
114+
}
115+
108116
let mut buf = String::new();
109-
send_request(&mut self.stdin, &mut self.stdout, req, &mut buf)
117+
send_request(&mut self.stdin, &mut self.stdout, req, &mut buf).map_err(|e| {
118+
if e.io.as_ref().map(|it| it.kind()) == Some(io::ErrorKind::BrokenPipe) {
119+
match self.process.child.try_wait() {
120+
Ok(None) => e,
121+
Ok(Some(status)) => {
122+
let mut msg = String::new();
123+
if !status.success() {
124+
if let Some(stderr) = self.process.child.stderr.as_mut() {
125+
_ = stderr.read_to_string(&mut msg);
126+
}
127+
}
128+
let server_error = ServerError {
129+
message: format!("server exited with {status}: {msg}"),
130+
io: None,
131+
};
132+
self.server_exited = Some(server_error.clone());
133+
server_error
134+
}
135+
Err(_) => e,
136+
}
137+
} else {
138+
e
139+
}
140+
})
110141
}
111142
}
112143

@@ -145,9 +176,13 @@ fn send_request(
145176
req: Request,
146177
buf: &mut String,
147178
) -> Result<Response, ServerError> {
148-
req.write(&mut writer)
149-
.map_err(|err| ServerError { message: "failed to write request".into(), io: Some(err) })?;
150-
let res = Response::read(&mut reader, buf)
151-
.map_err(|err| ServerError { message: "failed to read response".into(), io: Some(err) })?;
179+
req.write(&mut writer).map_err(|err| ServerError {
180+
message: "failed to write request".into(),
181+
io: Some(Arc::new(err)),
182+
})?;
183+
let res = Response::read(&mut reader, buf).map_err(|err| ServerError {
184+
message: "failed to read response".into(),
185+
io: Some(Arc::new(err)),
186+
})?;
152187
res.ok_or_else(|| ServerError { message: "server exited".into(), io: None })
153188
}

crates/proc-macro-srv-cli/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ fn main() -> std::io::Result<()> {
2424

2525
#[cfg(not(any(feature = "sysroot-abi", rust_analyzer)))]
2626
fn run() -> io::Result<()> {
27-
panic!("proc-macro-srv-cli requires the `sysroot-abi` feature to be enabled");
27+
eprintln!("proc-macro-srv-cli requires the `sysroot-abi` feature to be enabled");
28+
std::process::exit(70);
2829
}
2930

3031
#[cfg(any(feature = "sysroot-abi", rust_analyzer))]

0 commit comments

Comments
 (0)