2024-10-03 11:27:11 -05:00
|
|
|
//! Check that `rustc` and `rustdoc` does not ICE upon encountering a broken pipe due to unhandled
|
|
|
|
//! panics from raw std `println!` usages.
|
|
|
|
//!
|
|
|
|
//! Regression test for <https://github.com/rust-lang/rust/issues/34376>.
|
|
|
|
|
|
|
|
//@ ignore-cross-compile (needs to run test binary)
|
|
|
|
|
2024-10-08 23:49:27 -05:00
|
|
|
//@ ignore-apple
|
|
|
|
// FIXME(#131436): on macOS rustc is still reporting the std broken pipe io error panick but it
|
|
|
|
// doesn't fail with 101 exit status (it terminates with a wait status of SIGPIPE). It doesn't say
|
|
|
|
// Internal Compiler Error strangely, but it doesn't even go through normal diagnostic infra. Very
|
|
|
|
// strange.
|
|
|
|
|
2024-10-03 11:27:11 -05:00
|
|
|
#![feature(anonymous_pipe)]
|
|
|
|
|
|
|
|
use std::io::Read;
|
|
|
|
use std::process::{Command, Stdio};
|
|
|
|
|
|
|
|
use run_make_support::env_var;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
enum Binary {
|
|
|
|
Rustc,
|
|
|
|
Rustdoc,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) {
|
|
|
|
let (reader, writer) = std::pipe::pipe().unwrap();
|
|
|
|
drop(reader); // close read-end
|
|
|
|
cmd.stdout(writer).stderr(Stdio::piped());
|
|
|
|
|
|
|
|
let mut child = cmd.spawn().unwrap();
|
|
|
|
|
|
|
|
let mut stderr = String::new();
|
|
|
|
child.stderr.as_mut().unwrap().read_to_string(&mut stderr).unwrap();
|
|
|
|
let status = child.wait().unwrap();
|
|
|
|
|
|
|
|
assert!(!status.success(), "{bin:?} unexpectedly succeeded");
|
|
|
|
|
|
|
|
const PANIC_ICE_EXIT_CODE: i32 = 101;
|
|
|
|
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
{
|
|
|
|
// On non-Windows, rustc/rustdoc built with `-Zon-broken-pipe=kill` shouldn't have an exit
|
|
|
|
// code of 101 because it should have an wait status that corresponds to SIGPIPE signal
|
|
|
|
// number.
|
|
|
|
assert_ne!(status.code(), Some(PANIC_ICE_EXIT_CODE), "{bin:?}");
|
|
|
|
// And the stderr should be empty because rustc/rustdoc should've gotten killed.
|
|
|
|
assert!(stderr.is_empty(), "{bin:?} stderr:\n{}", stderr);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
{
|
|
|
|
match bin {
|
|
|
|
// On Windows, rustc has a paper that propagates the panic exit code of 101 but converts
|
|
|
|
// broken pipe errors into fatal errors instead of ICEs.
|
|
|
|
Binary::Rustc => {
|
|
|
|
assert_eq!(status.code(), Some(PANIC_ICE_EXIT_CODE), "{bin:?}");
|
|
|
|
// But make sure it doesn't manifest as an ICE.
|
|
|
|
assert!(!stderr.contains("internal compiler error"), "{bin:?} ICE'd");
|
|
|
|
}
|
|
|
|
// On Windows, rustdoc seems to cleanly exit with exit code of 1.
|
|
|
|
Binary::Rustdoc => {
|
|
|
|
assert_eq!(status.code(), Some(1), "{bin:?}");
|
|
|
|
assert!(!stderr.contains("panic"), "{bin:?} stderr contains panic");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let mut rustc = Command::new(env_var("RUSTC"));
|
|
|
|
rustc.arg("--print=sysroot");
|
|
|
|
check_broken_pipe_handled_gracefully(Binary::Rustc, rustc);
|
|
|
|
|
|
|
|
let mut rustdoc = Command::new(env_var("RUSTDOC"));
|
|
|
|
rustdoc.arg("--version");
|
|
|
|
check_broken_pipe_handled_gracefully(Binary::Rustdoc, rustdoc);
|
|
|
|
}
|