-
Couldn't load subscription status.
- Fork 13.9k
Prevent building cargo from invalidating build cache of other tools due to conditionally applied -Zon-broken-pipe=kill via tracked RUSTFLAGS
#131155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This comment has been minimized.
This comment has been minimized.
-Zon-broken-pipe=kill on rustc/rustdoc bin wrappers only-Zon-broken-pipe=kill via tracked RUSTFLAGS
-Zon-broken-pipe=kill via tracked RUSTFLAGS-Zon-broken-pipe=kill via tracked RUSTFLAGS
|
|
||
| fn main() { | ||
| let mut rustc = Command::new(env_var("RUSTC")); | ||
| rustc.arg("--print=sysroot"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this is technically not robust because I exploited the fact that --print=sysroot and friends usually use the raw println! which will panic upon encountering a broken pipe when rustc is not built with -Zon-broken-pipe=kill. Some outputs in rustc_driver_impl are correctly guarded by using safe_println! where they won't panic upon encountering a broken pipe even if -Zon-broken-pipe=kill is unset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but if -Zon-broken-pipe=kill is unset, safe_println will still emit an IO error, right? which is wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but if
-Zon-broken-pipe=killis unset,safe_printlnwill still emit an IO error, right? which is wrong
Yeah idk how specifically that will be handled, but that is left as an exercise for the future reader. Actually I think to clarify, I believe the safe_println in rustc_driver_impl is to convert the panic if -Zon-broken-pipe=kill is unset -> fatal error, just that it avoids an ICE, not necessarily the behavior one would want...
|
r? @onur-ozkan since you said you'd like to review this. Thanks for the help as well! |
-Zon-broken-pipe=kill via tracked RUSTFLAGS-Zon-broken-pipe=kill via tracked RUSTFLAGS
|
cc @rust-lang/cargo since this PR should not affect how cargo is built (i.e. cargo should still not be built with cc @rust-lang/rustdoc because rustdoc is also built (both before this PR and after) with |
| cmd.stdout(Stdio::piped()).stderr(Stdio::piped()); | ||
|
|
||
| let mut child = cmd.spawn().unwrap(); | ||
| // Close stdout | ||
| drop(child.stdout.take()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend caution with this approach, since it is inherently racey. For example, it assumes that it can close the handle before rustc is able to print. There can also be assumptions here about PIPE_BUF and other pipe behaviors. This can be unreliable on some systems. For example, on macOS, this should fail occasionally.
That's why cargo's tests which exercise this same behavior use a proc-macro to synchronize with rustc. (see here). That way the test can ensure that the handle is closed before rustc prints. Those tests also have some comments about the hazards of how this works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the context, I see why that test is so complex now...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted the test to use anonymous pipes instead which will make sure stdout is broken before the command is spawned.
I have to admit I have no idea. Being aligned with rustc seems the best course of action here. |
|
Changes since last review:
Not yet ready for another round of reviews, I still need to fix the test. |
ea62b8e to
b20436b
Compare
|
@bors rollup=never (subtle build system modifications and a run-make test that has platform-specific behaviors) |
|
Updated the rustc bin shim comment and fixed the regression test so this should now be ready for review. I ran the test locally on both:
@rustbot ready |
| // 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could try changing the windows hack to a early_fatal error:
rust/compiler/rustc_driver_impl/src/lib.rs
Line 1412 in cf24c73
| let _ = early_dcx.early_err(msg.clone()); |
1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll do that in a follow-up, I would like to stop run-make cargo rebuilds lol.
EDIT: actually I don't want to make the hack even hackier, this should be addressed by fixing the underlying cause and not add paper to the paper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair!
|
@bors r+ |
|
☀️ Test successful - checks-actions |
|
Finished benchmarking commit (18deb53): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)Results (primary -2.4%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 774.51s -> 774.814s (0.04%) |
Ignore broken-pipe-no-ice on apple (specifically macOS) for now This test fails for me locally (initially reported by Zalathar) because apparently on macOS it doesn't say "internal compiler error" but it does report the std I/O panic, and it doesn't exit with a code of 101 but instead terminates with a wait signal of SIGPIPE. Ignore this test on apple for now, until we try to actually address the underlying issue. See rust-lang#131155 and rust-lang#131436 for more context.
Ignore broken-pipe-no-ice on apple (specifically macOS) for now This test fails for me locally (initially reported by Zalathar) because apparently on macOS it doesn't say "internal compiler error" but it does report the std I/O panic, and it doesn't exit with a code of 101 but instead terminates with a wait signal of SIGPIPE. Ignore this test on apple for now, until we try to actually address the underlying issue. See rust-lang#131155 and rust-lang#131436 for more context.
Ignore broken-pipe-no-ice on apple (specifically macOS) for now This test fails for me locally (initially reported by Zalathar) because apparently on macOS it doesn't say "internal compiler error" but it does report the std I/O panic, and it doesn't exit with a code of 101 but instead terminates with a wait signal of SIGPIPE. Ignore this test on apple for now, until we try to actually address the underlying issue. See rust-lang#131155 and rust-lang#131436 for more context.
Rollup merge of rust-lang#131435 - jieyouxu:macos-pipe, r=Zalathar Ignore broken-pipe-no-ice on apple (specifically macOS) for now This test fails for me locally (initially reported by Zalathar) because apparently on macOS it doesn't say "internal compiler error" but it does report the std I/O panic, and it doesn't exit with a code of 101 but instead terminates with a wait signal of SIGPIPE. Ignore this test on apple for now, until we try to actually address the underlying issue. See rust-lang#131155 and rust-lang#131436 for more context.
Apply LTO config to rustdoc Before, the LTO configuration from `config.toml` was not applied to `rustdoc`. This provides a small perf. and binary size [win](rust-lang#112049 (comment)) for doc builds. Since this is configured with Cargo profiles and not rustflags, it should not break tool build cache (rust-lang#131155). I tried to run `x test miri`, `x test rustdoc` and `x test miri` and nothing was rebuilt. r? `@onur-ozkan`
Apply LTO config to rustdoc Before, the LTO configuration from `config.toml` was not applied to `rustdoc`. This provides a small perf. and binary size [win](rust-lang#112049 (comment)) for doc builds. Since this is configured with Cargo profiles and not rustflags, it should not break tool build cache (rust-lang#131155). I tried to run `x test miri`, `x test rustdoc` and `x test miri` and nothing was rebuilt. r? `@onur-ozkan`
Apply LTO config to rustdoc Before, the LTO configuration from `config.toml` was not applied to `rustdoc`. This provides a small perf. and binary size [win](rust-lang/rust#112049 (comment)) for doc builds. Since this is configured with Cargo profiles and not rustflags, it should not break tool build cache (rust-lang/rust#131155). I tried to run `x test miri`, `x test rustdoc` and `x test miri` and nothing was rebuilt. r? `@onur-ozkan`
Apply LTO config to rustdoc Before, the LTO configuration from `config.toml` was not applied to `rustdoc`. This provides a small perf. and binary size [win](rust-lang/rust#112049 (comment)) for doc builds. Since this is configured with Cargo profiles and not rustflags, it should not break tool build cache (rust-lang/rust#131155). I tried to run `x test miri`, `x test rustdoc` and `x test miri` and nothing was rebuilt. r? `@onur-ozkan`
This PR fixes #130980 where building cargo invalidated the tool build caches of other tools (such as rustdoc) because
-Zon-broken-pipe=killwas conditionally passed viaRUSTFLAGSfor other tools except for cargo. The differingRUSTFLAGStriggered tool build cache invalidation asRUSTFLAGSis a tracked env var -- any changes inRUSTFLAGSrequires a rebuild.-Zon-broken-pipe=killis load-bearing for rustc and rustdoc to not ICE on broken pipes due to usages of raw stdprintln!that panics without the flag being set, which manifests in ICEs.I can't say I like the changes here, but it is what it is...
See detailed discussions and history of
-Zon-broken-pipe=killusage in https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Internal.20lint.20for.20raw.20.60print!.60.20and.20.60println!.60.3F/near/474593815.Approach
This PR fixes the tool build cache invalidation by informing the
rustcbinary shim when to apply-Zon-broken-pipe=kill(i.e. when the rustc binary shim is not used to build cargo). This information is not communicated byRUSTFLAGS, which is an env var tracked by cargo, and instead uses an untracked env varUNTRACKED_BROKEN_PIPE_FLAGso we won't trigger tool build cache invalidation. We preserve bootstrap's behavior of not setting that flag for cargo by conditionally omitting settingUNTRACKED_BROKEN_PIPE_FLAGwhen building cargo.Notably, the
-Zon-broken-pipe=killinstance inrust/src/bootstrap/src/core/build_steps/compile.rs
Line 1058 in 1e5719b
Thanks to @cuviper for the idea!
Testing
Integration testing
This PR introduces a run-make test for rustc and rustdoc that checks that when they do not ICE/panic when they encounter a broken pipe of the stdout stream.
I checked this test will catch the broken pipe ICE regression for rustc on Linux (at least) by commenting out
rust/src/bootstrap/src/core/build_steps/compile.rs
Line 1058 in 1e5719b
Manual testing
I have manually tried:
./x clean &&./x test build --stage 1->rustc +stage1 --print=sysroot | false`: no ICE../x clean->./x test run-maketwice: no stage 1 cargo rebuilds../x clean->./x build rustdoc->rustdoc +stage1 --version | false: no panics../x test src/tools/cargo: tests pass, notablybuild::close_outputandcargo_command::closed_output_okdo not fail which would fail if cargo was built with-Zon-broken-pipe=kill.Related discussions
Thanks to everyone who helped!
Fixes #130980
Closes #131059
try-job: aarch64-apple
try-job: x86_64-msvc
try-job: x86_64-mingw