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

ICE abort due to nested panic while panic-unwinding inside a proc-macro #106298

Open
Veetaha opened this issue Dec 30, 2022 · 6 comments
Open

ICE abort due to nested panic while panic-unwinding inside a proc-macro #106298

Veetaha opened this issue Dec 30, 2022 · 6 comments
Labels
A-error-handling Area: Error handling A-proc-macros Area: Procedural macros C-bug Category: This is a bug. glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Veetaha
Copy link
Contributor

Veetaha commented Dec 30, 2022

I tried this code:

// lib.rs
#[derive(from_variants::FromVariants)]
pub(crate) enum FooBarity {
    Bar(bool, u8),
}

A ready-made repository with the reproduction is here.

The version of from_variants crate is 1.0.0.

I expected to see this happen:

This is not the intended usage of FromVariants proc macro. It expects an enum with tuple-style variants of a single arity. Best would be if FromVariants reported this as a pretty compile error with proper spans, but even if the implementation of proc macro fails to do that, then rustc shouldn't abort on a double-panic. The compiler should report that there is an error in exactly "this proc macro" and the output of the proc macro was "this".

Instead, this happened:
Rustc aborted, and the following output was seen in the terminal:

cargo check
   Compiling proc-macro2 v1.0.49
   Compiling quote v1.0.23
   Compiling unicode-ident v1.0.6
   Compiling syn v1.0.107
   Compiling ident_case v1.0.1
   Compiling fnv v1.0.7
   Compiling strsim v0.10.0
   Compiling darling_core v0.13.4
   Compiling darling_macro v0.13.4
   Compiling darling v0.13.4
   Compiling from_variants_impl v1.0.0
    Checking from_variants v1.0.0
    Checking rustc-ice-double-panic-reproduction v0.1.0 (/home/veetaha/dev/rustc-ice-double-panic-reproduction)
thread panicked while panicking. aborting.
error: could not compile `rustc-ice-double-panic-reproduction`

Caused by:
  process didn't exit successfully: `rustc --crate-name rustc_ice_double_panic_reproduction --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 -C metadata=59bd2ae5acf02373 -C extra-filename=-59bd2ae5acf02373 --out-dir /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps -C incremental=/home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/incremental -L dependency=/home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps --extern from_variants=/home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants-efa1e139161f23f5.rmeta` (signal: 6, SIGABRT: process abort signal)

Meta

The problem does reproduce both on stable and nightly versions of rustc and cargo:

Stable:

  • cargo 1.66.0 (d65d197ad 2022-11-15)
  • rustc 1.66.0 (69f9c33d7 2022-12-12)

Nightly:

  • rustc 1.66.0 (69f9c33d7 2022-12-12)
  • rustc 1.68.0-nightly (ad8ae0504 2022-12-29)

Unfortunately, RUST_BACTRACE=1 doesn't seem to produce a stack trace. I suppose it's because this is an abort.

But here is a snippet of the log of running RUSTC_LOG=trace cargo +nightly check:

Stripped version of the log that "might" be of interest
INFO rustc_metadata::creader resolving dep crate from_variants_impl hash: `1e48d5fccc90ee71` extra filename: `-51d45b4cefdd50d8`
INFO rustc_metadata::creader resolving crate `from_variants_impl`
INFO rustc_metadata::creader falling back to a load
INFO rustc_metadata::locator lib candidate: /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants_impl-51d45b4cefdd50d8.so
INFO rustc_metadata::locator dylib reading metadata from: /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants_impl-51d45b4cefdd50d8.so
INFO rustc_metadata::locator Rejecting via proc macro: expected false got true
INFO rustc_metadata::locator metadata mismatch
INFO rustc_metadata::locator lib candidate: /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants_impl-51d45b4cefdd50d8.so
INFO rustc_metadata::locator lib candidate: /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants_impl-cd9b885ca1b6ee81.so
INFO rustc_metadata::locator dylib reading metadata from: /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants_impl-cd9b885ca1b6ee81.so
INFO rustc_metadata::locator Rejecting via version: expected rustc 1.68.0-nightly (ad8ae0504 2022-12-29) got rustc 1.66.0 (69f9c33d7 2022-12-12)
INFO rustc_metadata::locator metadata mismatch
INFO rustc_metadata::locator lib candidate: /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants_impl-51d45b4cefdd50d8.so
INFO rustc_metadata::locator dylib reading metadata from: /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants_impl-51d45b4cefdd50d8.so
INFO rustc_metadata::creader register crate `from_variants_impl` (cnum = 21. private_dep = false)
INFO rustc_metadata::creader resolving crate `from_variants`
thread panicked while panicking. aborting.
error: could not compile `rustc-ice-double-panic-reproduction`

Caused by:
  process didn't exit successfully: `rustc --crate-name rustc_ice_double_panic_reproduction --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=151 --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 -C metadata=4365a24095010a27 -C extra-filename=-4365a24095010a27 --out-dir /home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps -C incremental=/home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/incremental -L dependency=/home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps --extern from_variants=/home/veetaha/dev/rustc-ice-double-panic-reproduction/target/debug/deps/libfrom_variants-f46dfc5abe2fbb3e.rmeta` (signal: 6, SIGABRT: process abort signal)

But here is the full log anyway:

rustc-trace-full.log

@Veetaha Veetaha added the C-bug Category: This is a bug. label Dec 30, 2022
@Veetaha
Copy link
Contributor Author

Veetaha commented Dec 30, 2022

cc @TedDriggs (the author of from_variants, just for your information)

@JohnTitor JohnTitor added I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ and removed I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. labels Dec 31, 2022
@pnkfelix
Copy link
Member

pnkfelix commented Jan 13, 2023

Note: Since the from_variants crate has been since updated, the problem described here does not duplicate via the steps described unless you use the Cargo.lock file that is part of the linked repository.


In any case, I have narrowed the problem down to a simple MCVE, which one can observe by putting the following files into the appropriate locations in the test/ui/ directory:

File: test/ui/proc-macro/issue-106298-double-panic-in-proc-macro.rs

// aux-build:double-panic-during-expand.rs

#[macro_use]
extern crate double_panic_during_expand;

#[derive(double_panic_during_expand::Panic)]
struct S { x: u8 }

fn main() { }

File: test/ui/proc-macro/auxilliary/double-panic-during-expand.rs

// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
struct PanicOnDrop;

impl Drop for PanicOnDrop {
    fn drop(&mut self) { panic!("panic on drop!"); }
}

#[proc_macro_derive(Panic)]
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let _p_on_d = PanicOnDrop;
    panic!("panic during panic-during-expand's derive")
}

With the above files in place, for me running x.py test --stage 1 tests/ui/proc-macro yields:

failures:

---- [ui] rust.git/tests/ui/proc-macro/issue-106298-double-panic-in-proc-macro.rs stdout ----

error: Error: expected failure status (Some(1)) but received status None.
status: signal: 6 (SIGABRT) (core dumped)
command: <snip>
stdout: none
--- stderr -------------------------------
thread panicked while panicking. aborting.
------------------------------------------



failures:
    [ui] rust.git/tests/ui/proc-macro/issue-106298-double-panic-in-proc-macro.rs

@pnkfelix
Copy link
Member

@rustbot label: -E-needs-mcve

@rustbot rustbot removed the E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example label Jan 13, 2023
@pnkfelix pnkfelix changed the title ICE: thread panicked while panicking. aborting. (100% reproduction) ICE abort due to nested panic while panic-unwinding inside a proc-macro Jan 13, 2023
@pnkfelix pnkfelix added the A-proc-macros Area: Procedural macros label Jan 13, 2023
@pnkfelix
Copy link
Member

Today, if you pass -Z proc-macro-backtrace during the final rustc invocation, you at least get a stack trace dump for the first panic that occurs (before unwinding starts), i.e. the panic!("panic during panic-during-expand's derive") in my example above.

We may want to consider turning on the top level panic output, without the stack trace, unconditionally, in order to improve the user experience here when one encounters an abort due to a nested panic during the unwinding of the macro.

@pnkfelix
Copy link
Member

Given that we already abort on double-panic, the main alternative I can see to turning on top-level panic output unconditionally is to allow code more ability to customize the message that's printed when we do abort due to a double-panic.

It can't be anything too sophisticated, because at the point where we're responding to a double-panic, we're already assuming we cannot allocate etc.

But just being able to override (temporarily) the message with a different &'static str, e.g.: "panicked during unwinding from macro expansion" or something along those lines, would be better here than the current flat "thread panicked while panicking. aborting." that supplies no contextual information at all about where the problem arose.

@rust-lang-glacier-bot rust-lang-glacier-bot added the glacier ICE tracked in rust-lang/glacier. label Jan 14, 2023
@fmease
Copy link
Member

fmease commented Jan 18, 2023

allow code more ability to customize the message that's printed when we do abort due to a double-panic.

The proc_macro crate currently installs the panic hook (that hides the backtrace unless -Zproc-macro-backtrace is set) here:

maybe_install_panic_hook(force_show_panics);

The code that emits the aforementioned error message shown for double panics can be found here in the std crate:

rtprintpanic!("thread panicked while panicking. aborting.\n");

In order for the two separate programs to communicate, the panic hook either needs to be able to return something other than () which the linked code can then pick up (this isn't really an option since we would either need to backward-incompatibly change the signatures of {set,take,update}_hook or uglily create a new alternative set for handling hooks) or a new concept next to hooks has to be invented along with a separate API.

My point being it doesn't look simple :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-error-handling Area: Error handling A-proc-macros Area: Procedural macros C-bug Category: This is a bug. glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants