-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Prevent building cargo from invalidating build cache of other tools due to conditionally applied -Zon-broken-pipe=kill
via tracked RUSTFLAGS
#131155
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=kill
is unset,safe_println
will 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
This comment was marked as outdated.
This comment was marked as outdated.
This comment has been minimized.
This comment has been minimized.
This comment was marked as outdated.
This comment was marked as outdated.
- Don't touch rustc's `-Zon-broken-pipe=kill` env var in `compile.rs`. - Use an untracked env var to pass `-Zon-broken-pipe=kill` for tools but skip cargo still, because cargo wants `-Zon-broken-pipe=kill` unset.
@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.
This PR fixes #130980 where building cargo invalidated the tool build caches of other tools (such as rustdoc) because
-Zon-broken-pipe=kill
was conditionally passed viaRUSTFLAGS
for other tools except for cargo. The differingRUSTFLAGS
triggered tool build cache invalidation asRUSTFLAGS
is a tracked env var -- any changes inRUSTFLAGS
requires a rebuild.-Zon-broken-pipe=kill
is 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=kill
usage 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
rustc
binary 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_FLAG
so 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_FLAG
when building cargo.Notably, the
-Zon-broken-pipe=kill
instance 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-make
twice: 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_output
andcargo_command::closed_output_ok
do 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