Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 37 additions & 29 deletions src/toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,47 +284,55 @@ impl<'a> Toolchain<'a> {
#[tracing::instrument(level = "trace")]
pub fn rustc_version(&self) -> String {
match self.create_command("rustc") {
Err(e) => format!("(rustc does not exist: {e})"),
Ok(mut cmd) => {
cmd.arg("--version");
cmd.stdin(Stdio::null());
cmd.stdout(Stdio::piped());
cmd.stderr(Stdio::piped());
self.set_ldpath(&mut cmd);

// some toolchains are faulty with some combinations of platforms and
// may fail to launch but also to timely terminate.
// (known cases include Rust 1.3.0 through 1.10.0 in recent macOS Sierra.)
// we guard against such cases by enforcing a reasonable timeout to read.
let mut line1 = None;
if let Ok(mut child) = cmd.spawn() {
let timeout = Duration::new(10, 0);
match child.wait_timeout(timeout) {
Ok(Some(status)) if status.success() => {
let out = child
.stdout
.expect("Child::stdout requested but not present");
let mut line = String::new();
if BufReader::new(out).read_line(&mut line).is_ok() {
let lineend = line.trim_end_matches(&['\r', '\n'][..]).len();
line.truncate(lineend);
line1 = Some(line);
match cmd.spawn() {
Err(e) => {
format!("(error reading rustc version: {e})")
}
// some toolchains are faulty with some combinations of platforms and
// may fail to launch but also to timely terminate.
// (known cases include Rust 1.3.0 through 1.10.0 in recent macOS Sierra.)
// we guard against such cases by enforcing a reasonable timeout to read.
Ok(mut child) => {
let timeout = Duration::new(10, 0);
match child.wait_timeout(timeout) {
Ok(None) => {
let _ = child.kill();
String::from("(timeout reading rustc version)")
}
Err(e) => {
format!("(error reading rustc version: {e})")
}
Ok(Some(status)) => {
if !status.success() {
return format!("(error reading rustc version: {status})");
}

let out = child
.stdout
.expect("Child::stdout requested but not present");
let mut line = String::new();
match BufReader::new(out).read_line(&mut line) {
Ok(_) => {
let lineend =
line.trim_end_matches(&['\r', '\n'][..]).len();
line.truncate(lineend);
line
}
Err(e) => format!("(error reading rustc version: {e})"),
}
}
}
Ok(None) => {
let _ = child.kill();
return String::from("(timeout reading rustc version)");
}
Ok(Some(_)) | Err(_) => {}
}
}

if let Some(line1) = line1 {
line1
} else {
String::from("(error reading rustc version)")
}
}
Err(_) => String::from("(rustc does not exist)"),
}
}

Expand Down