Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce timeouts for reading rustc version. #1071

Merged
merged 1 commit into from
Apr 19, 2017
Merged
Show file tree
Hide file tree
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
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