Code change:
In <https://rust- identified the root cause of (unnecessary stage 1 cargo rebuilds) being The other instance of this is As (thank you so much) pointed out: I tried to limit application of to and binary wrappers in themselves, and unfortunately this leads to two cargo test failures: <details<summaryPrevious history</summaryI'm putting up a PR () to remove conditionally adding , and as we expect two cargo tests to be broken with if that is unconditionally passed to bootstrap. I don't know if this breaks someone's workflow regarding to piping cargo tool tests, but in the interest of not making everyone rebuild stage1 cargo on every single invocation of , I'm considering this as "known breakage" for the time being. As suggested: </details
cc team in case anyone has any advice regarding these two tests.
cc if you have any advice since this was in for (it didn't occur to me that adding would cause build cache invalidation problems), presumably to workaround the cargo test failures.
Thanks for the ping. Unfortunately I currently do not have the time to look into this.
No worries that is fine, pinged just in case you had immediate context or advice.
Maybe we should only run those two tests in rust-lang/cargo CI?
Can you give some more context? What are the benefits and drawbacks of ? What does that look like to the user of and ? I don't quite understand . It looks like it regresses something, but I'm not clear what. If it is breaking cargo tests, how is it possible for that PR to land? It seems like removing would be regressing whatever issue it was to fix in the first place, but I don't know what that is.
The linked PR does not break Cargo tests, it possibly breaks someone's contributor workflow that relies on bootstrap implicitly setting . Bootstrap can't implicitly set that flag for everything, or it breaks Cargo's tests. The bug here is that none of the numerous people who looked at the original PR (including me) noticed that the right thing to do here is not set the flag at all, because inconsistent flag-setting creates spurious rebuilds.
Yeah sorry I didn't know how to word the issue title accurately (please rename this issue if there's an more accurate description), will remove conditionally passed flags passed to cargo from bootstrap, which might break someone's workflow related to running cargo tool tests through bootstrap if they wanted to do something like (AFAICT) because now we don't pass at all, but unconditionally setting will cause the aforementioned test failures. EDIT: I tried to fixup the issue description and title to be more accurate.
Sorry, I'm still not clear what is being changed or what is being proposed. Also, sorry for many questions, but I don't have context on what is going on. What happens after when someone does ? What happened before? Is the concern after specifically about , or is it all bootstrap commands? Some of them? Does change the dist artifacts? If so, how? How much of this is specific to using versus using and ? Is there an original issue related to bootstrap workflows that initiated the introduction of ? Who is asking for a different behavior? Looking at , it seems like this stems back to . How does rustc now handle sigpipe? My naive thinking is that removing causes that to regress, but it doesn't seem like that is what you are proposing, and clearly no tests are being broken. But I don't see how all these pieces fit together.
only affects the entry point. Setting it on libraries is useless. I think could be used to add flags that only effect the final build and not any dependency.
... Actually thanks for asking these questions, it seems that simply removing these flags to fix rebuilds will regress rustc (and probably rustdoc) behavior with respect to broken pipes. rustc will ICE locally (e.g. , i.e. reintroduces ) without being built with that flag being set. The context is that I was trying to make not have to rebuild stage1 cargo even if nothing changed, because was not universally applied to tool builds (specifically excluding cargo), which causes tool build cache invalidation because stage1 cargo has to be rebuilt due to the differing flags. I will revert , investigate why regression test for rustc doesn't catch the broken pipe ICE, and reinvestigate what is going on with .
Apparently it does, I'm putting up a revert now. This unfortunately affects how itself is built. This was originally related to where we changed from the in-source attribute of UI to a command-line UI , so they were in an attempt to preserve the existing behavior of kill process if pipe is broken, instead of panicking (and possibly leading to an ICE for rustc specifically). Apparently through that flag when the main binary is being built. AFAICT your suspicions are correct, and indeed removing the flag will regress that. I don't know why no tests are being broken, which probably means no tests were actually exercising this behavior.
I tried to do some digging, and here's what I came up with. Note: the following investigation is to the best of my understanding and most likely contains inaccuracies and misleading representations, reader discretion is required In , the UI of changed to become an unstable rustc flag (cf. stabilization comment ). corresponds to . Not setting will default to . Note that this default behavior will lead to panic in Rust programs if the pipe is broken (e.g in a simple program ). For rustc binary it means the unexpected panic will be caught by the ICE handler manifesting in an ICE . For other tools like rustdoc or cargo it depends on how unexpected panics are handled, but nothing good. removed from rustc and rustdoc (i.e. from their binaries), and set to preserve kill-process-on-broken-pipe behavior to not have the panics and ICEs. Before was available, was addressed by adding a sigpipe handler in rustcdriver explicitly, as done in . But this was changed in for rustc and in for rustdoc to use which was intended to be a more reusable mechanism. Now removed attribute meaning that those flags are load-bearing, for building rustc and rustdoc binaries. Cargo might not be affected itself if it uses its own sigpipe handling, but I have not investigated that specifically.In to help with , we addedIn we moved being set only for tool build from to to help mitigate rebuilds for Miri tests (because setting only for rustdoc means if you build another tool, the tool build cache will get invalidated due to differing ). Note that this particular instance of is for tool builds and cargo, there is a different instance of for building the rustc binary itself in . Conditionally omitting for cargo itself does not cause tool build cache invalidation before (and ) because we were simply using bootstrap cargo (or rather, in bootstrap terms) and not try to build stage 1 cargo ourselves. Only tests want to build stage 1 cargo, even miri tests just use initial cargo. Now that tests builds stage 1 cargo, the omitted for cargo tool build specifically will lead to tool build cache invalidation due to differing . Note that I don't fully understand how tool build caches work and why differing for one of the tools can lead to tool build cache invalidation for all of the tools built from the same stage compiler.I tried to remove both instances of : The instance in : this I suspect was intended for binary. Now I think I understand I cannot remove this flag, because to at least binary I believe is load-bearing for kill-process-on-broken-pipe behavior due to UI changes to command-line flag as aforementioned. Not sure how cargo tests are affected, which is why the flag is not unconditionally always set in the first place. The instance in : this I definitely should not have removed because as I described previously is now load-bearing for the binary for kill-process-on-broken-pipe, otherwise it will reintroduce . I intend to revert now that I have a better understanding of why these flags are even there in the first place, and not having the flags set regresses broken-pipe behavior for and at the minimum. This effect includes dist builds of them so I practically introduced a P-critical regression to and if not also for other tools. I intend to try unconditionally set for all tool builds in so that (1) it preserves desired kill-process-on-broken-pipe behavior for and other tools that are typical of cli tools and (2) it should not cause tool build cache invalidation because it is not conditionally absent from cargo. I intend to investigate/fix a few things: Work with T-cargo and T-bootstrap to figure out why some cargo tests may fail on and either fix those tests and/or fix how cargo is building itself. Investigate why zero tests failed in full CI and locally, in both rustc and rustdoc test suites, even if I reintroduce the ICE for rustc and a similar panic for rustdoc. I intend to add regression tests for and for this behavior specifically, or fix the existing tests that didn't test what they intended to test.
I tried to update PR title and PR description to better reflect the current understanding regarding the two cargo test failures related to changing where is applied in bootstrap.

Related discussion:
text: <ins> //! 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) #![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); } </ins>