diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 90fd31ecbdd73..bf1da57607d5f 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -68,6 +68,7 @@ fn main() {
     };
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
     let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
+    let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
 
     let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
     let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -212,9 +213,20 @@ fn main() {
     }
 
     // Actually run the compiler!
-    std::process::exit(match exec_cmd(&mut cmd) {
-        Ok(s) => s.code().unwrap_or(0xfe),
-        Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
+    std::process::exit(if let Some(ref mut on_fail) = on_fail {
+        match cmd.status() {
+            Ok(s) if s.success() => 0,
+            _ => {
+                println!("\nDid not run successfully:\n{:?}\n-------------", cmd);
+                exec_cmd(on_fail).expect("could not run the backup command");
+                1
+            }
+        }
+    } else {
+        std::process::exit(match exec_cmd(&mut cmd) {
+            Ok(s) => s.code().unwrap_or(0xfe),
+            Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
+        })
     })
 }
 
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index c5bbfd89b2787..b55f3d710ca7b 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -28,6 +28,7 @@ use step;
 /// Deserialized version of all flags for this compile.
 pub struct Flags {
     pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
+    pub on_fail: Option<String>,
     pub stage: Option<u32>,
     pub keep_stage: Option<u32>,
     pub build: String,
@@ -81,6 +82,7 @@ impl Flags {
         opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
         opts.optmulti("", "host", "host targets to build", "HOST");
         opts.optmulti("", "target", "target targets to build", "TARGET");
+        opts.optopt("", "on-fail", "command to run on failure", "CMD");
         opts.optopt("", "stage", "stage to build", "N");
         opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
         opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
@@ -283,6 +285,7 @@ To learn more about a subcommand, run `./x.py <command> -h`
         Flags {
             verbose: m.opt_count("v"),
             stage: stage,
+            on_fail: m.opt_str("on-fail"),
             keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()),
             build: m.opt_str("build").unwrap_or_else(|| {
                 env::var("BUILD").unwrap()
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 7bd611eb53e3c..a28cb24a8166f 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -499,6 +499,10 @@ impl Build {
             cargo.env("RUSTC_INCREMENTAL", incr_dir);
         }
 
+        if let Some(ref on_fail) = self.flags.on_fail {
+            cargo.env("RUSTC_ON_FAIL", on_fail);
+        }
+
         let verbose = cmp::max(self.config.verbose, self.flags.verbose);
         cargo.env("RUSTC_VERBOSE", format!("{}", verbose));