about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2019-06-27 02:14:57 -0700
committerAlex Crichton <alex@alexcrichton.com>2019-06-27 02:23:06 -0700
commitb6087492ed7b78096adbdba1e086cc987f46b32d (patch)
tree98c5622d6dff04dbf041dd05fb98a1f07d18c5df /src
parentd3e2cec29225a46298ec4ebf082f34ebd7cfeecf (diff)
downloadrust-b6087492ed7b78096adbdba1e086cc987f46b32d.tar.gz
rust-b6087492ed7b78096adbdba1e086cc987f46b32d.zip
rustc: Retry SIGILL linker invocations
We've seen quite a few issues with spurious illegal instructions getting
executed on OSX on CI recently. For whatever reason `cc` itself is
executing an illegal instruction and we're not really getting any other
information about what's happening. Since we're already retrying the
linker when it segfaults, let's just continue to retry everything and
automatically reinvoke the linker when it fails with an illegal instruction.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_ssa/back/link.rs71
1 files changed, 47 insertions, 24 deletions
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 0ba5451bd72..618e8b8699f 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -29,7 +29,7 @@ use std::fmt;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
-use std::process::{Output, Stdio};
+use std::process::{Output, Stdio, ExitStatus};
 use std::str;
 use std::env;
 
@@ -510,21 +510,6 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
     sess.abort_if_errors();
 
     // Invoke the system linker
-    //
-    // Note that there's a terribly awful hack that really shouldn't be present
-    // in any compiler. Here an environment variable is supported to
-    // automatically retry the linker invocation if the linker looks like it
-    // segfaulted.
-    //
-    // Gee that seems odd, normally segfaults are things we want to know about!
-    // Unfortunately though in rust-lang/rust#38878 we're experiencing the
-    // linker segfaulting on Travis quite a bit which is causing quite a bit of
-    // pain to land PRs when they spuriously fail due to a segfault.
-    //
-    // The issue #38878 has some more debugging information on it as well, but
-    // this unfortunately looks like it's just a race condition in macOS's linker
-    // with some thread pool working in the background. It seems that no one
-    // currently knows a fix for this so in the meantime we're left with this...
     info!("{:?}", &cmd);
     let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
     let mut prog;
@@ -567,21 +552,59 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
             info!("{:?}", &cmd);
             continue;
         }
+
+        // Here's a terribly awful hack that really shouldn't be present in any
+        // compiler. Here an environment variable is supported to automatically
+        // retry the linker invocation if the linker looks like it segfaulted.
+        //
+        // Gee that seems odd, normally segfaults are things we want to know
+        // about!  Unfortunately though in rust-lang/rust#38878 we're
+        // experiencing the linker segfaulting on Travis quite a bit which is
+        // causing quite a bit of pain to land PRs when they spuriously fail
+        // due to a segfault.
+        //
+        // The issue #38878 has some more debugging information on it as well,
+        // but this unfortunately looks like it's just a race condition in
+        // macOS's linker with some thread pool working in the background. It
+        // seems that no one currently knows a fix for this so in the meantime
+        // we're left with this...
         if !retry_on_segfault || i > 3 {
             break
         }
         let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
         let msg_bus  = "clang: error: unable to execute command: Bus error: 10";
-        if !(out.contains(msg_segv) || out.contains(msg_bus)) {
-            break
+        if out.contains(msg_segv) || out.contains(msg_bus) {
+            warn!(
+                "looks like the linker segfaulted when we tried to call it, \
+                 automatically retrying again. cmd = {:?}, out = {}.",
+                cmd,
+                out,
+            );
+            continue;
         }
 
-        warn!(
-            "looks like the linker segfaulted when we tried to call it, \
-             automatically retrying again. cmd = {:?}, out = {}.",
-            cmd,
-            out,
-        );
+        if is_illegal_instruction(&output.status) {
+            warn!(
+                "looks like the linker hit an illegal instruction when we \
+                 tried to call it, automatically retrying again. cmd = {:?}, ]\
+                 out = {}, status = {}.",
+                cmd,
+                out,
+                output.status,
+            );
+            continue;
+        }
+
+        #[cfg(unix)]
+        fn is_illegal_instruction(status: &ExitStatus) -> bool {
+            use std::os::unix::prelude::*;
+            status.signal() == Some(libc::SIGILL)
+        }
+
+        #[cfg(windows)]
+        fn is_illegal_instruction(_status: &ExitStatus) -> bool {
+            false
+        }
     }
 
     match prog {