Skip to content

Commit

Permalink
Merge pull request #1071 from lifthrasiir/rustc-version-timeout
Browse files Browse the repository at this point in the history
Enforce timeouts for reading rustc version.
  • Loading branch information
Diggsey authored Apr 19, 2017
2 parents 8cb95b8 + 809bff6 commit 332dc61
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ rustc-serialize = "0.3"
sha2 = "0.1.2"
markdown = "0.2"
toml = "0.1.27"
wait-timeout = "0.1.5"

[target."cfg(windows)".dependencies]
winapi = "0.2.8"
Expand Down
36 changes: 30 additions & 6 deletions src/rustup-cli/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ use errors::*;
use rustup_utils::utils;
use rustup_utils::notify::NotificationLevel;
use self_update;
use std::io::{Write, BufRead};
use std::process::Command;
use std::io::{Write, BufRead, BufReader};
use std::process::{Command, Stdio};
use std::path::Path;
use std::{cmp, iter};
use std::sync::Arc;
use std::time::Duration;
use std;
use term2;
use wait_timeout::ChildExt;

pub fn confirm(question: &str, default: bool) -> Result<bool> {
print!("{} ", question);
Expand Down Expand Up @@ -222,12 +224,34 @@ pub fn rustc_version(toolchain: &Toolchain) -> String {
if utils::is_file(&rustc_path) {
let mut cmd = Command::new(&rustc_path);
cmd.arg("--version");
cmd.stdin(Stdio::null());
cmd.stdout(Stdio::piped());
cmd.stderr(Stdio::piped());
toolchain.set_ldpath(&mut cmd);

let out= cmd.output().ok();
let out = out.into_iter().find(|o| o.status.success());
let stdout = out.and_then(|o| String::from_utf8(o.stdout).ok());
let line1 = stdout.and_then(|o| o.lines().next().map(|l| l.to_owned()));
// 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(1, 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_right_matches(&['\r', '\n'][..]).len();
line.truncate(lineend);
line1 = Some(line);
}
}
Ok(None) => {
let _ = child.kill();
}
Ok(Some(_)) | Err(_) => {}
}
}

if let Some(line1) = line1 {
line1.to_owned()
Expand Down
1 change: 1 addition & 0 deletions src/rustup-cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ extern crate tempdir;
extern crate sha2;
extern crate markdown;
extern crate toml;
extern crate wait_timeout;

#[cfg(windows)]
extern crate gcc;
Expand Down

0 comments on commit 332dc61

Please sign in to comment.