diff --git a/.travis.yml b/.travis.yml index fa6c9cf074864..42684d70d36a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,6 +44,7 @@ matrix: RUST_CHECK_TARGET=check RUST_CONFIGURE_ARGS=--build=x86_64-apple-darwin SRC=. + RUSTC_RETRY_LINKER_ON_SEGFAULT=1 os: osx osx_image: xcode8.2 install: &osx_install_sccache > @@ -53,6 +54,7 @@ matrix: RUST_CHECK_TARGET=check RUST_CONFIGURE_ARGS=--build=i686-apple-darwin SRC=. + RUSTC_RETRY_LINKER_ON_SEGFAULT=1 os: osx osx_image: xcode8.2 install: *osx_install_sccache @@ -62,6 +64,7 @@ matrix: RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended" SRC=. DEPLOY=1 + RUSTC_RETRY_LINKER_ON_SEGFAULT=1 os: osx osx_image: xcode8.2 install: > @@ -74,6 +77,7 @@ matrix: RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended" SRC=. DEPLOY=1 + RUSTC_RETRY_LINKER_ON_SEGFAULT=1 os: osx osx_image: xcode8.2 install: *osx_install_sccache @@ -88,6 +92,7 @@ matrix: RUST_CONFIGURE_ARGS="--enable-extended" SRC=. DEPLOY_ALT=1 + RUSTC_RETRY_LINKER_ON_SEGFAULT=1 os: osx osx_image: xcode8.2 install: *osx_install_sccache diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index b58f96033bf5b..a1703b1c155eb 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -752,8 +752,54 @@ fn link_natively(sess: &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 OSX'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 prog = time(sess.time_passes(), "running linker", || cmd.output()); + let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok(); + let mut prog; + let mut i = 0; + loop { + i += 1; + prog = time(sess.time_passes(), "running linker", || cmd.output()); + if !retry_on_segfault || i > 3 { + break + } + let output = match prog { + Ok(ref output) => output, + Err(_) => break, + }; + if output.status.success() { + break + } + let mut out = output.stderr.clone(); + out.extend(&output.stdout); + let out = String::from_utf8_lossy(&out); + let msg = "clang: error: unable to execute command: \ + Segmentation fault: 11"; + if !out.contains(msg) { + break + } + + sess.struct_warn("looks like the linker segfaulted when we tried to \ + call it, automatically retrying again") + .note(&format!("{:?}", cmd)) + .note(&out) + .emit(); + } + match prog { Ok(prog) => { fn escape_string(s: &[u8]) -> String {