This document explains what Crubit's rs_bindings_from_cc
and cc_bindings_from_rs
tools do to handle Rust panics and C++ exceptions.
“Alright so I'm panicking, what else is there to do?”
-- “The Hitchhiker’s Guide to the Galaxy” by Douglas Adams
Rust libraries built with -Cpanic=abort
terminate their process upon panic and there isn‘t much else to do. Similarly, C++ libraries built with Clang’s -fno-exceptions
flag terminate the process when a C++ exception is thrown.
In build environments that use the flags above, Rust panics and C++ exceptions don‘t unwind the callstack looking for appropriate handlers. This means that bindings generated by Crubit’s rs_bindings_from_cc
and cc_bindings_from_rs
tools don't need to do anything special to handle panics and/or exceptions. In particular, Rust calls into C++ (and C++ calls into Rust) can just use the “C” ABI and assume that no panics and no exceptions will ever need to unwind across the FFI boundary.
Currently Crubit-generated bindings only support -Cpanic=abort
, -fno-exceptions
environment. See the “Exceptions” section in the Google C++ Style Guide for discussion of some of the pros and cons of an -fno-exceptions
environment.
TODO(b/254049425): Add support for cross-FFI unwinding of Rust panics and C++ exceptions.
“Who said anything about panicking?” snapped Arthur. “This is still just the culture shock. You wait till I‘ve settled down into the situation and found my bearings. Then I’ll start panicking.”
-- “The Hitchhiker’s Guide to the Galaxy” by Douglas Adams
Crubit doesn't currently support unwinding of Rust panics or C++ exceptions across the FFI boundary. In other words, the generated bindings are only safe when -Cpanic=abort
and -fno-exceptions
are used - other configurations may lead to Undefined Behavior:
C++ exception unwinding through Rust frames leads to Undefined Behavior (based on this part of RFC 2945).
Rust panic unwinding through C++ frames leads to Undefined Behavior. Note that RFC 2945 defines some of that behavior: “with the panic=unwind
runtime, panic!
will cause an abort if it would otherwise “escape” from a function defined with extern "C"
.”
Below is an incomplete, tentative list of steps needed to add Crubit support for cross-language unwinding of panics and exceptions:
Support building Crubit's automated tests with -Cpanic=unwind
and/or -fexceptions
. Use this support to add test coverage for:
If one or both languages don't abort on unwind, then modify the generated Rust code to use the new "C-unwind"
ABI string proposed by RFC 2945 (instead of using the old "C"
ABI string):
rs_bindings_from_cc
should use "C-unwind"
ABI when declaring C++ thunks in mod detail
in the generated ..._rs_api.rs
cc_bindings_from_rs
should use "C-unwind"
ABI when defining C++ thunks in ..._cc_api_impl.rs
Investigate if Crubit needs to modify the generated C++ code. For example:
rs_bindings_from_cc
in ..._rs_api_impl.cc
.cc_bindings_from_rs
in ..._cc_api.h
.