4 ms·
I find the relationship between mutlithreading and panics' default behavior confusing. In a single-threaded program, a panic is not supposed to be "caught" and
by ilyagr 2y ago
I find the relationship between mutlithreading and panics' default behavior confusing.
In a single-threaded program, a panic is not supposed to be "caught" and aborts everything. If the main thread panics, the program stops.
But in a multi-threaded program, a panic terminates only the thread it happened in, and the program is allowed to handle that case without termination.
I'm guessing that setting `panic=abort` changes this behavior, but I'm not sure.
Docs: https://doc.rust-lang.org/std/macro.panic.html#current-implementation https://doc.rust-lang.org/std/macro.panic.html#current-imple..., the third sentence of https://doc.rust-lang.org/std/thread/fn.spawn.html https://doc.rust-lang.org/std/thread/fn.spawn.html
- zamalek 2y agoYour assumptions about panic=abort are correct, it will simply terminate the entire process. The single thread and multithreaded behaviors are technically the same. A thread can observe the panic of another, as such, in a single threaded app, which thread would observe the panic in the main thread? There is no other thread to do that. What you could do is create a single new thread and pretend as though its the main thread, observing any panics on the original main thread. Edit: your mental model should be to avoid thinking about panics (beyond avoiding them in the first place). Panics are supposed to be extremely rare, and typically something that would be difficult to recover from. They are not exceptions; they are not designed to be caught. The difficulty in dealing with them is a feature that prevents anti patterns. If something panics you have a bug.
- SAI_Peregrinus 2y agoThe last paragraph is particularly important! Catching panics in Rust is meant pretty much only to avoid unwinding across an FFI boundary, since that would be undefined behavior. Pretty much every other use of `catch_unwind` is a mistake, it's not guaranteed to catch all panics (they can also just abort) so panics are rather different from exceptions. Panics are intended to be useless for control flow, unwinding exists to help debugging, and any panic indicates a bug in the invoking program.
- ilyagr 2y agoFrom this perspective, the weird part is that mutli-threaded programs can recover from panics in some of the threads (as long as `panic=unwind`). I suppose it's so practically useful that people made an exception for it, without this feature people would have to do inter-process communication (for better or worse).
- wabain 2y agoI think what's really special about the main thread is that Rust (and I believe in some cases the OS) forces the process to exit if the main thread completes. I think the difference in panic handling is mostly down to that. I think the description in the docs for std::thread describe this distinction the most explicitly.[1] Fundamentally panic recovery works the same way in all threads—for both the main thread and spawned threads the standard library implements panic handling by wrapping the user code in catch_unwind().[2][3] It's more or less possible to override the standard library's behavior for the main thread by wrapping all the code in your main() function in a catch_unwind() and then implementing whatever fallback behavior you want, like waiting for other threads to exit before terminating. In some cases something like this happens automatically, for instance if the main thread spawns other threads using std::thread::scope.[4] [1]: https://doc.rust-lang.org/std/thread/#the-threading-model https://doc.rust-lang.org/std/thread/#the-threading-model [2]: https://github.com/rust-lang/rust/blob/7042c269c166191cd5d8daf0409890903df7af57/library/std/src/thread/mod.rs#L521-L523 https://github.com/rust-lang/rust/blob/7042c269c166191cd5d8d... [3]: https://github.com/rust-lang/rust/blob/7042c269c166191cd5d8daf0409890903df7af57/library/std/src/rt.rs#L143-L147 https://github.com/rust-lang/rust/blob/7042c269c166191cd5d8d... [4]: https://doc.rust-lang.org/std/thread/fn.scope.html https://doc.rust-lang.org/std/thread/fn.scope.html