-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
catch_unwind incorrectly tries to stop ForceUnwinds #65441
Comments
I feel that we should simply let all foreign exceptions unwind through |
Note that C++ with Itanium ABI also catches foreign exceptions if a |
Actually, looking at the implementation of |
Yes, I think that's correct at the language spec level, because right now, letting a foreign exception (or any kind of exception actually) unwind into Rust is UB, so we do not provide any kind of guarantees about what As you mention, what we currently do for foreign exceptions is horrible. Since there are some platforms where we can easily do better (e.g. just aborting), I think we should do so as a "quality-of-implementation" issue at least, even though it is still UB. |
Allow foreign exceptions to unwind through Rust code This PR allows C++ exceptions (and any other exceptions) to safely unwind through Rust code. In particular: - Drop code will be executed as the exception unwinds through the stack, as with a Rust panic. - `catch_unwind` will *not* catch the exception, instead the exception will silently continue unwinding past it. Incidentally, Rust panics can unwind just fine through C++ code as long as you mark the function with `#[unwind(allowed)]`. I've added a test for it to be sure. I haven't updated any of the documentation, so officially unwinding through FFI is still UB. However this is a step towards making it well-defined. Fixes #65441 cc @gnzlbg r? @alexcrichton
Allow foreign exceptions to unwind through Rust code This PR allows C++ exceptions (and any other exceptions) to safely unwind through Rust code. In particular: - Drop code will be executed as the exception unwinds through the stack, as with a Rust panic. - `catch_unwind` will *not* catch the exception, instead the exception will silently continue unwinding past it. Incidentally, Rust panics can unwind just fine through C++ code as long as you mark the function with `#[unwind(allowed)]`. I've added a test for it to be sure. I haven't updated any of the documentation, so officially unwinding through FFI is still UB. However this is a step towards making it well-defined. Fixes #65441 cc @gnzlbg r? @alexcrichton
Allow foreign exceptions to unwind through Rust code This PR allows C++ exceptions (and any other exceptions) to safely unwind through Rust code. In particular: - Drop code will be executed as the exception unwinds through the stack, as with a Rust panic. - `catch_unwind` will *not* catch the exception, instead the exception will silently continue unwinding past it. Incidentally, Rust panics can unwind just fine through C++ code as long as you mark the function with `#[unwind(allowed)]`. I've added a test for it to be sure. I haven't updated any of the documentation, so officially unwinding through FFI is still UB. However this is a step towards making it well-defined. Fixes #65441 cc @gnzlbg r? @alexcrichton
Allow foreign exceptions to unwind through Rust code This PR allows C++ exceptions (and any other exceptions) to safely unwind through Rust code. In particular: - Drop code will be executed as the exception unwinds through the stack, as with a Rust panic. - `catch_unwind` will *not* catch the exception, instead the exception will silently continue unwinding past it. Incidentally, Rust panics can unwind just fine through C++ code as long as you mark the function with `#[unwind(allowed)]`. I've added a test for it to be sure. I haven't updated any of the documentation, so officially unwinding through FFI is still UB. However this is a step towards making it well-defined. Fixes #65441 cc @gnzlbg r? @alexcrichton
Allow foreign exceptions to unwind through Rust code and Rust panics to unwind through FFI This PR fixes interactions between Rust panics and foreign (mainly C++) exceptions. C++ exceptions (and other FFI exceptions) can now safely unwind through Rust code: - The FFI function causing the unwind must be marked with `#[unwind(allowed)]`. If this is not the case then LLVM may optimize landing pads away with the assumption that they are unreachable. - Drop code will be executed as the exception unwinds through the stack, as with a Rust panic. - `catch_unwind` will *not* catch the exception, instead the exception will silently continue unwinding past it. Rust panics can now safely unwind through C++ code: - C++ destructors will be called as the stack unwinds. - The Rust panic can only be caught with `catch (...)`, after which it can be either rethrown or discarded. - C++ cannot name the type of the Rust exception object used for unwinding, which means that it can't be caught explicitly or have its contents inspected. Tests have been added to ensure all of the above works correctly. Some notes about non-C++ exceptions: - `pthread_cancel` and `pthread_exit` use unwinding on glibc. This has the same behavior as a C++ exception: destructors are run but it cannot be caught by `catch_unwind`. - `longjmp` on Windows is implemented using unwinding. Destructors are run on MSVC, but not on MinGW. In both cases the unwind cannot be caught by `catch_unwind`. - As with C++ exceptions, you need to mark the relevant FFI functions with `#[unwind(allowed)]`, otherwise LLVM will optimize out the destructors since they seem unreachable. I haven't updated any of the documentation, so officially unwinding through FFI is still UB. However this is a step towards making it well-defined. Fixes #65441 cc @gnzlbg r? @alexcrichton
MWE:
(Playground)
Output:
Errors:
According to the Itanium ABI:
So
catch_unwind
definitely needs to always catch Rust exceptions, and at the thread boundary it probably also want to catch foreign exceptions and abort since whatever that should do probably won't work. When not on a thread boundary, aborting on foreign exceptions might be a conservative step until a better solution is discussed (an alternative solution would be not to catch them and just let them escape, or to catch them and have theAny
be someForeignPanic
type defined somewhere instd::panic
that users can use to detect that a foreign exception was raised). What it probably shouldn't do is catch "ForceUnwind" otherwiselongjmp
might not work across it and threads will not be canceled, but... maybe the conservative thing to do would be for this to abort for the time being?The text was updated successfully, but these errors were encountered: