5 ms·
Agreed. The whole panic situation is an awful mess that the Rust designers refuse to deal with. It's the sort of thing you put into a language when it's a toy
by KirillPanov 6y ago
Agreed. The whole panic situation is an awful mess that the Rust designers refuse to deal with. It's the sort of thing you put into a language when it's a toy, but Rust isn't a toy anymore and they refuse to do any of these:
* remove it
* make panics reliably "catch"-able 100% of the time like thrown exceptions (in languages with exceptions)
* make it possible to statically check panic-safety, the way we check unsafe {}
The dodge I always hear is "yeah but your code could always go off into an infinite loop, and we'll never be able to prevent or detect that". Okay, but nobody uses "while(1){}" as a deliberate response to an error condition. The Rust standard library is jammed full of code that will deliberately panic if tickled the wrong way.
Look, I love Rust, but the denial around panic is just ridiculous. We need "might_panic" annotations, enforced exactly the way "unsafe" annotations are enforced, and the standard library needs to be updated to provide them. Bite the bullet. Linus is right. This should have happened years ago.
- salicideblock 6y agoHear hear! Here's to hoping that inclusion in the kernel will provide the motivation for addressing this in Rust. This is a point that may benefit from the new backing of Rust by the foundation - non-userspace was a side thing for Mozilla, but in Google and Amazon they have some core stuff depending on kernel.
- bitlevel 6y agoHere's to hoping it goes nowhere near the kernel until the Rust developers address it first, not the other way round.
- littlestymaar 6y agoThis comment is strongly missinformed: 1- panicking allocations are here to stay, because in lots of case, it's the most convenient behavior. BUT Rust is adding fallible allocations methods (prefixed with try_) which return a result instead of panicking on allocation failure. 2- panics are catch-able as long as you don't compile your binary with panic=abort setting (and as long as you don't panic in your panic handler itself (including in your types' destructor, which are called during stack unwinding)) 3- panics can only occur in specific places (array indexing, allocations, utf-8 validation, unwrap, etc.) which are by definition known at compile-time, and there's tooling to catch these up [1]. In practice, a might_panic annotation would add a lot of noise for pretty much everybody, because most of us mortals use panicking function all days and it's not a big deal. Obviously it is critical for Linux, but because it's relevant only to the minority of Rust users, it doesn't make sense to include it in rustc itself: it's exactly the kind of situation where external tooling is the good option. [1] https://github.com/Technolution/rustig https://github.com/Technolution/rustig
- KirillPanov 6y agoThis comment is strongly confused about typechecking. > [1] https://github.com/Technolution/rustig https://github.com/Technolution/rustig That's a binary analysis tool (for x86_64 only!). It is only approximate, and does not claim to be an accurate analysis like typechecks (such as the unsafe check) are: https://github.com/Technolution/rustig#limitations https://github.com/Technolution/rustig#limitations > All paths leading to panic! from one of those functions (whether actually used or not) will be reported. Crude binary analyses like these lack the critical efficiency and predictability properties of type checks: * Typechecks like the unsafe-check can be done on each module in isolation, using the code from that module and only the types (not the code) from any modules that it calls. This is the essential property that makes typechecking efficient enough to run on every compilation. * If each module separately passes the check, then a program using both of them passes the check. This is the essential property that makes typechecking predictable enough to produce useful error messages. This binary analysis tool operates on the whole program. Turning optimizations on and off will cause the tool to switch from reporting "ok" to reporting false positives. Pretending that a tool like this is a replacement for a typechecker amounts to grossly negligent software engineering. Panics are an ugly leftover from the bad old days before Rust had nice monad-like "?" syntax for Result<T,E> error-handling. It's time for unrestricted panic to sunset. The Rust community has waited too long to do this, which is why it will be painful. Waiting longer will only make it even more painful. > panics are catch-able False. Unwinding panics runs drop handlers; if one of these drop handlers itself panics, Rust just sort of throws its hands up in the air and aborts the process no matter what: > Given that a panic! will call drop() as it unwinds, any panic! in a drop() implementation will likely abort. https://doc.rust-lang.org/std/ops/trait.Drop.html#panics https://doc.rust-lang.org/std/ops/trait.Drop.html#panics The panic mess is full of nasty ill-defined edge cases like this. It's gotta go.
- littlestymaar 6y agoPanics are useful, because no-one wants to clutter their function signature with errors that are in fact invariant assertions. Granted, It's not elegant, but it does the job. Expressing potentially panicking functions in the typesystem (or an effect system) would add little benefit for most users, given that even the Linux kernel is likely to use panics (with the panic handler calling BUG) for things that represent broken invariants (array overflow, assert, etc) and it's not really possible to do because integer overflow have a different behavior depending on whether they are in debug or in release mode. Since it's a really niche use-case, it makes total sense to be an external tool. > > panics are catch-able > False. Unwinding panics runs drop handlers; if one of these drop handlers itself panics, You didn't really read my previous comment right? (emphasis mine, to give you some help) > panics are catch-able as long as you don't compile your binary with panic=abort setting (and as long as you don't panic in your panic handler itself (including in your types' destructor, which are called during stack unwinding))
- TickleSteve 6y agoIts quite common to use "while(true);" in the embedded world in order to trigger the hardware watchdog and cause a reset in a panic situation. It indicates that the only sensible option is to reset the processor to get back to a known-good state. This is pretty much how you handle unrecoverable errors in the embedded world where you must always take account of what happens in a reset condition for all situations and maintain 100% uptime because no one is going to reset it manually.
- KirillPanov 6y agoNo, it is not common at all. You simply jump to the watchdog interrupt handler, or execute the "reset the CPU" instruction. No need for such convoluted foolery with loops and timeouts to achieve exactly the same effect. Remember, embedded processors have no MMU -- there's no context switch when entering an interrupt handler.