Skip to content
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

Add -Z panic-in-drop={unwind,abort} command-line option #88759

Merged
merged 5 commits into from
Sep 12, 2021

Conversation

Amanieu
Copy link
Member

@Amanieu Amanieu commented Sep 8, 2021

This PR changes Drop to abort if an unwinding panic attempts to escape it, making the process abort instead. This has several benefits:

  • The current behavior when unwinding out of Drop is very unintuitive and easy to miss: unwinding continues, but the remaining drops in scope are simply leaked.
  • A lot of unsafe code doesn't expect drops to unwind, which can lead to unsoundness:
  • There is a code size and compilation time cost to this: LLVM needs to generate extra landing pads out of all calls in a drop implementation. This can compound when functions are inlined since unwinding will then continue on to process drops in the callee, which can itself unwind, etc.
    • Initial measurements show a 3% size reduction and up to 10% compilation time reduction on some crates (syn).

One thing to note about -Z panic-in-drop=abort is that all crates must be built with this option for it to be sound since it makes the compiler assume that dropping Box<dyn Any> will never unwind.

cc rust-lang/lang-team#97

@rust-highfive
Copy link
Collaborator

r? @estebank

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 8, 2021
@Amanieu
Copy link
Member Author

Amanieu commented Sep 8, 2021

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Sep 8, 2021
@bors
Copy link
Contributor

bors commented Sep 8, 2021

⌛ Trying commit 75b61d15a9d844666c07d09064bec26a595d83fd with merge 1f815a30705b7e96c149fc4fa88a98ca04e2deee...

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Sep 8, 2021

☀️ Try build successful - checks-actions
Build commit: 1f815a30705b7e96c149fc4fa88a98ca04e2deee (1f815a30705b7e96c149fc4fa88a98ca04e2deee)

@rust-timer
Copy link
Collaborator

Queued 1f815a30705b7e96c149fc4fa88a98ca04e2deee with parent c9db3e0, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (1f815a30705b7e96c149fc4fa88a98ca04e2deee): comparison url.

Summary: This change led to large relevant mixed results 🤷 in compiler performance.

  • Large improvement in instruction counts (up to -9.9% on full builds of syn)
  • Large regression in instruction counts (up to 2.0% on full builds of keccak)

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR led to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Sep 9, 2021
@jyn514
Copy link
Member

jyn514 commented Sep 9, 2021

One thing to note about -Z panic-in-drop=abort is that all crates must be built with this option for it to be sound since it makes the compiler assume that dropping Box will never unwind.

Could we make it a hard error if there's a mismatch in this between crates?

@Amanieu
Copy link
Member Author

Amanieu commented Sep 9, 2021

Could we make it a hard error if there's a mismatch in this between crates?

Where would be the best place to add this check? Do we have any precedent for validating crate compatibility?

@ghost
Copy link

ghost commented Sep 9, 2021

I think there is a similar check here:

// Next up, verify that all other crates are compatible with this panic
// strategy. If the dep isn't linked, we ignore it, and if our strategy
// is abort then it's compatible with everything. Otherwise all crates'
// panic strategy must match our own.
for (i, linkage) in list.iter().enumerate() {
if let Linkage::NotLinked = *linkage {
continue;
}
if desired_strategy == PanicStrategy::Abort {
continue;
}
let cnum = CrateNum::new(i + 1);
let found_strategy = tcx.panic_strategy(cnum);
let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
if is_compiler_builtins || desired_strategy == found_strategy {
continue;
}
sess.err(&format!(
"the crate `{}` is compiled with the \
panic strategy `{}` which is \
incompatible with this crate's \
strategy of `{}`",
tcx.crate_name(cnum),
found_strategy.desc(),
desired_strategy.desc()
));
}

@Amanieu
Copy link
Member Author

Amanieu commented Sep 9, 2021

This shaves 5MB off librustc_driver.so, a 3% reduction (197MB -> 192MB).

@joshtriplett
Copy link
Member

This looks really promising!

I think this would be a good first step. Before we can even consider changing the default behavior, we'd need to have an option for the new behavior, and experiment with it extensively.

@estebank
Copy link
Contributor

Can somebody else in @rust-lang/compiler take this review on? I am not as confident in codegen as the rest of the compiler.

@eddyb
Copy link
Member

eddyb commented Sep 10, 2021

r? @nagisa cc @nikic @wesleywiser

@rust-highfive rust-highfive assigned nagisa and unassigned estebank Sep 10, 2021
Copy link
Member

@eddyb eddyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far, but I'd like to review test changes once the drop_in_place lang item isn't spuriously required, which seems to account for a lot of them.

compiler/rustc_codegen_llvm/src/abi.rs Outdated Show resolved Hide resolved
compiler/rustc_metadata/src/dependency_format.rs Outdated Show resolved Hide resolved
compiler/rustc_typeck/src/collect.rs Outdated Show resolved Hide resolved
src/test/ui/asm/inline-syntax.rs Outdated Show resolved Hide resolved
@nagisa
Copy link
Member

nagisa commented Sep 10, 2021

Another thing to add on a quick skim: in MIR when building cleanup blocks, we spend a lot of effort to build unwind ladders just in case a cleanup/drop panics. All of that can also be disabled when this flag is enabled, potentially giving you another significant perf boost in build times.

@Amanieu Amanieu marked this pull request as ready for review September 10, 2021 22:57
@Amanieu
Copy link
Member Author

Amanieu commented Sep 10, 2021

I've addressed all the review feedback.

I'm having a bit of trouble wrapping my head around the drop tree building code, so I haven't made any changes there yet.

compiler/rustc_codegen_llvm/src/abi.rs Outdated Show resolved Hide resolved
compiler/rustc_codegen_llvm/src/abi.rs Outdated Show resolved Hide resolved
compiler/rustc_middle/src/ty/layout.rs Outdated Show resolved Hide resolved
compiler/rustc_target/src/abi/call/mod.rs Outdated Show resolved Hide resolved
compiler/rustc_mir_build/src/build/expr/into.rs Outdated Show resolved Hide resolved
@Amanieu
Copy link
Member Author

Amanieu commented Sep 11, 2021

Addressed feedback.

Comment on lines +1197 to +1198
panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED],
"panic strategy for panics in drops"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add accepted values list and default (like in some other options), plus maybe unstable book entry?

@nagisa
Copy link
Member

nagisa commented Sep 12, 2021

@bors r=nagisa,eddyb

I think this is reasonable starting point. I suspect there are more places we can reduce the amount of work we do, but there's no reason for all that to be covered in this specific PR.

@bors
Copy link
Contributor

bors commented Sep 12, 2021

📌 Commit 5862a00 has been approved by nagisa,eddyb

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 12, 2021
@bors
Copy link
Contributor

bors commented Sep 12, 2021

⌛ Testing commit 5862a00 with merge 51e514c...

@bors
Copy link
Contributor

bors commented Sep 12, 2021

☀️ Test successful - checks-actions
Approved by: nagisa,eddyb
Pushing 51e514c to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 12, 2021
@bors bors merged commit 51e514c into rust-lang:master Sep 12, 2021
@rustbot rustbot added this to the 1.57.0 milestone Sep 12, 2021
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (51e514c): comparison url.

Summary: This benchmark run did not return any relevant changes.

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

@rustbot label: -perf-regression

@rustbot rustbot removed the perf-regression Performance regression. label Sep 13, 2021
@Amanieu Amanieu changed the title Add -Z panic-in-drop={unwind,abort} command-line option Add -Z panic-in-drop={panic,abort} command-line option Oct 6, 2021
@Amanieu Amanieu changed the title Add -Z panic-in-drop={panic,abort} command-line option Add -Z panic-in-drop={unwind,abort} command-line option Oct 6, 2021
@Wyvern
Copy link

Wyvern commented Apr 16, 2023

Now, I use "-Zpanic-in-drop=abort" and build-std to build rust project hit lots of errors, like below:

error: the crate `std` is compiled with the panic-in-drop strategy `unwind` which is incompatible with this crate's strategy of `abort`

error: the crate `core` is compiled with the panic-in-drop strategy `unwind` which is incompatible with this crate's strategy of `abort`

error: the crate `rustc_std_workspace_core` is compiled with the panic-in-drop strategy `unwind` which is incompatible with this crate's strategy of `abort`

error: the crate `alloc` is compiled with the panic-in-drop strategy `unwind` which is incompatible with this crate's strategy of `abort`

error: the crate `libc` is compiled with the panic-in-drop strategy `unwind` which is incompatible with this crate's strategy of `abort`

Anybody knows how to resolve it?

@Amanieu
Copy link
Member Author

Amanieu commented Apr 21, 2023

Now, I use "-Zpanic-in-drop=abort" and build-std to build rust project hit lots of errors, like below:

It seems to work fine for me:

RUSTFLAGS=-Zpanic-in-drop=abort cargo build -Zbuild-std --target x86_64-unknown-linux-gnu

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.