Share some opinions about Unwind vs. Abort?

Few days ago, I join the thread (Panic: Unwind vs. Abort - help - The Rust Programming Language Forum) which was opened six years ago. I think it would be better to move the discussion here because the issue was too old.

I am still interested in the way how everyone decides to use unwinding or abort in rust. I would love to share my personal opinions first to launch the discussion thread (Feel free to correct me if I am wrong)

To cleanup the allocated resource

With unwinding, we can customize drop implementation to keep system in consistent state. With abort, we are not able to expect how system clean the resource, and it's highly possible to leave system in inconsistent state.

To be used in FFI

It is still a difficult problem to use unwinding in FFI. Not to mention that unwinding is a complex mechanism, it is hard to define the behaviors across different language stack frames and lead to UB. Though unwind-suffix ABI is supported in the future, the interaction with forced unwinding (e.g., C) is still UB. In this case, abort is preferred if we cannot use error code.

To catch unwinding and recover from it

In FFI, developers try using catch_unwind to stop panic propagating and recover from it. However, catch_unwind is not easy to use correctly. I am still just keep impl UnwindSafe for my own data type because it is hard for me to determine whether it is unwind safe.

Do people really care about broken logic invariants from UnwindSafe?

I am working on building a rust binding, so I have more considerations in FFI scenario.

Appreciate any discussion!

If you're writing a Rust library, it's not your choice. You have to support both:

  • ensure the code remains safe (and preferably well-behaved) when something unwinds. This is especially important when calling user code in unsafe {} blocks. You need to be aware that operator overloading can call user code too, and unwind (even Deref!)
  • but you can't rely on unwinding being enabled, so don't use it for control flow or error reporting, except unrecoverable errors that are program bugs. For all other errors use Result.
7 Likes

impl UnwindSafe is about if the value stays logically consistent so for example if you have a data structure that is expected to stay sorted you can implement UnwindSafe if none of the exposed operations can violate this invariant by panicking. However if you depend on it staying sorted to avoid UB, you must abort (std::process::abort()) if a panic would cause it to stop being sorted. By the way UnwindSafe is an auto trait, so if all fields implement it, the type itself will also implement it.

2 Likes