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

Panic within a panic causes illegal instruction SIGILL #53814

Closed
sunjay opened this issue Aug 30, 2018 · 2 comments
Closed

Panic within a panic causes illegal instruction SIGILL #53814

sunjay opened this issue Aug 30, 2018 · 2 comments

Comments

@sunjay
Copy link
Member

sunjay commented Aug 30, 2018

See first comment for an even smaller example of the issue. Thanks @mgattozzi for the insight that led to that!

I was integrating NonZeroU8 into some code when I ran into an illegal instruction error that looks like this:

thread panicked while panicking. aborting.
error: process didn't exit successfully: `/path/to/my/project/target/debug/deps/xxxx-b71130afded4f9e4` (signal: 4, SIGILL: illegal instruction)

I spent a really long time trying to narrow this down and I got down to the following contrived example: (Rust Playground)

use std::{
    fmt,
    num::NonZeroU8,
};

pub struct Foo;

impl fmt::Display for Foo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", NonZeroU8::new(0).unwrap())
    }
}

#[test]
fn something() {
    panic!("{}", Foo);
}

This probably looks like super weird code that no one would ever write, but this started from some real code I promise. 😆

The key part of this code is:

NonZeroU8::new(0).unwrap()

The illegal instruction error occurs whenever that 0 is any value less than or equal to zero. You may be asking yourself "How do you make a u8 literal less than zero?" Well you don't. Rust protects you from that. The thing that Rust doesn't protect you from is this: (Rust Playground)

let y = 3;
let x = 2 - y;
write!(f, "{}", NonZeroU8::new(x).unwrap())

The variable x will be -1 and the code will produce the same illegal instruction error.

Some weird things to note about this:

  • It seems to work when run with cargo run. The failure is on cargo test.
  • I haven't figured out how to recreate this without the impl of Display. Inlining does NOT produce the error:
// No illegal instructions for this code!
use std::num::NonZeroU8;

#[test]
fn something() {
    panic!("{}", NonZeroU8::new(0).unwrap());
}
@sunjay
Copy link
Member Author

sunjay commented Aug 30, 2018

The real MVP @mgattozzi realized what the problem was in a second. The display impl panics within the panic in the test and that's what causes the problem. Here's an even more minimal reproduction:

use std::fmt;

pub struct Foo;

impl fmt::Display for Foo {
    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
        panic!()
    }
}

#[test]
fn something() {
    panic!("{}", Foo);
}
thread panicked while panicking. aborting.
error: process didn't exit successfully: `/playground/target/debug/deps/playground-b71130afded4f9e4` (signal: 4, SIGILL: illegal instruction)

I guess you could say I did a good job writing this issue given that someone was able to take a cursory look at it and figure out so much. Sorry I didn't catch it myself! 😆

@sunjay sunjay changed the title NonZeroU8::new(0) sometimes causes illegal instruction SIGILL Panic within a panic causes illegal instruction SIGILL Aug 30, 2018
@sunjay
Copy link
Member Author

sunjay commented Aug 30, 2018

I'm going to close this issue because I think this is expected behaviour.

I totally misunderstood the bug and thought it was happening during compilation. Sorry about that folks! 😨

Looks like it's time for me to go to bed. 😴

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant