ffi-unwind 2020-01-13

scenarios

  • what kinds of things can be propagated
  • panics
  • foreign exceptions
  • “forced unwinds”
  • these are meant to be “invisible” to the language, language users aren’t really meant to interact with them
  • C++ lets you catch them but perhaps it shouldn’t
  • arise from longjmp in MSVC
  • arise from pthread_exit in some pthread implementations (GNU C but not MUSL)
  • in glibc, this will unwind the stack to the root of the thread
  • in MUSL, pthread exit just frees the stack immediately, Rust cannot handle this
  • maybe arise from various C functions due to pthread_cancel
  • C++ (or other language, perhaps) exceptions 
  • “painless subset”
  • catching panics
  • propagating foreign exceptions across frames without destructors
  • core requirement of Rust
  • it has to be UB to unwind a Rust frame w/o executing a destructor within
  • C++ presumably calls this UB too? not entirely clear
  • tricky problems
  • under panic=abort:
  • do we want to enable longjmp with -Cpanic=abort (across frames that have no destructors)?
  • if you do, then you can’t locally detect foreign unwinding at the “C/unwind” call site
  • possible solutions
  • Option 1: “2 APIs, always permit forced unwinding”
  • introduce C and C unwind
  • the C ABI:
  • it is UB to unwind, except for a forced unwind without a destructor in scope, regardless of -Cpanic=unwind or -Cpanic=abort
  • this allows us to abort in extern "C" fn() if we so choose, except for forced unwinding, we could also abort at call sites in debug builds
  • also, this means you can use longjmp with “C” ABI, so long as you know there are no destructors in scope
  • the “C unwind” ABI:
  • -Cpanic=unwind
  • a Rust panic is defined behavior
  • it is UB for a forced unwinding or longjmp if there are destructors in scope
  • (but on some platforms it may execute destructors)
  • other foreign exceptions are defined behavior (?)
  • -Cpanic=abort
  • Rust panics will abort and will not propagate
  • add a shim that permits forced unwinding to propagate but aborts otherwise
  • Pros:
  • if you are working with C++, you start to get aborts instead of exceptions
  • we can use “C” ABI for read, so long as you won’t run dtors
  • Cpanic=abort cannot introduce UB
  • minimal overhead for shims because “C unwind” is unusual
  • Cons:
  • but pthread_cancel cannot be combined with destructors
  • unless we say that it’s not UB if you are on the right platforms and have panic=unwind (but then panic=abort introduces UB in that case)
  • Option 1b: 
  • as above, except that “C unwind” treats all foreign exceptions the same