Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design for panic-via-exception handling (and vice versa) #1184

Open
schreter opened this issue Feb 26, 2023 · 3 comments
Open

Design for panic-via-exception handling (and vice versa) #1184

schreter opened this issue Feb 26, 2023 · 3 comments

Comments

@schreter
Copy link
Contributor

In our project which requires perfect C++/Rust integration regarding error handling we extended cxx crate to handle panics as C++ exceptions as well. This works well, however, the panic is only handled whenever the Rust function returns a Result (as otherwise C++ exception is not generated at all). The question is, how can we handle panics also in non-Result functions returning only the value.

There are following possibilities:

  • Do not handle it at all, i.e., keep status quo and only handle it in Result functions (that's the current state of implementation, which I can push upstream).
  • Handle panics in general for all Rust functions and throw them as a RustPanic exception in C++. This requires the change of the generated code on the C++ side.

Of course, we prefer the latter, since that would transparently handle all Rust errors and propagate them to C++ without crashing the program because of stumbling over the ABI boundary (and transparent C++/Rust integration is the goal of cxx crate 🙂).

However, since in principle any Rust function can panic, implementing this requires indirect return for all values. Considering that the bridge is relatively "heavyweight" anyway, this should be no big issue, though. Aside from that, cross-language LTO will remove unnecessary moves, effectively producing (almost) optimal code.

The inverse issue, handling C++ exceptions via panics in non-Result C++ functions is the same in green - again, it would entail an indirect return and handling the exception by turning it into a panic in the Rust part of the bridge. We can even transparently pass the C++ exception through Rust frames with this, so outer C++ calling Rust calling inner C++ throwing exception will land in the outer C++ with exactly the same exception thrown in the inner C++ code (there is already a pending change #1180 to handle C++ exceptions transparently, so we can build on top of it).

Therefore, are there any objections against changing the generator to always handle the return value via an indirection, so we can reliably turn panics to C++ exceptions and vice versa (possibly configurable on bridge level)? If so, what is the alternative? If not, I'd go with the implementation in that direction.

Alternatively, does anyone have a better idea how to handle it?

Any other ideas/proposals/wishes regarding this topic?

Thanks.

@dtolnay
Copy link
Owner

dtolnay commented Feb 26, 2023

I would be on board with turning all Rust panicks to C++ exceptions (throw rust::Panic) and C++ exceptions to Rust panicks.

@schreter
Copy link
Contributor Author

@dtolnay

I would be on board with turning all Rust panicks to C++ exceptions (throw rust::Panic) and C++ exceptions to Rust panicks.

Perfect. But just to reiterate, this also means that we need to return values via indirect return in all cases, which might be potential performance regression (though my hope is that LTO will fix that). Is that fine from your POV? Thanks.

@dtolnay
Copy link
Owner

dtolnay commented Feb 27, 2023

That's fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants