-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Abort in cleanup leads to unwinding failure #61945
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
Comments
@llvm/issue-subscribers-clang-codegen |
cc @efriedma-quic for unwinding This regressed due to https://reviews.llvm.org/D145210, but that's only because we are now better at inferring |
From C++ [except.handle]: If no matching handler is found, the function std::terminate is invoked; whether or not the stack is unwound before this invocation of std::terminate is implementation-defined I think libunwind prefers to terminate before unwinding. Given that, I think we should not infer nounwind for abort_in_dtor; even though control flow never actually unwinds past it, the first pass of unwinding does try to look through it. |
Yeah, that sounds like a pragmatic fix. Would it be fine to just special-case cleanup landingpads in FunctionAttrs inference, without actually making them mayThrow()? |
Special-case seems fine; it's not actually control flow in the sense most users of mayThrow() care about. |
Candidate patch: https://reviews.llvm.org/D147694 |
Currently, FunctionAttrs treats landingpads as non-throwing, and will infer nounwind for functions with landingpads (assuming they can't unwind in some other way, e.g. via resum). There are two problems with this: * Non-cleanup landingpads with catch/filter clauses do not necessarily catch all exceptions. Unless there are catch ptr null or filter [0 x ptr] zeroinitializer clauses, we should assume that we may unwind past this landingpad. This seems like an outright bug. * Cleanup landingpads are skipped during phase one unwinding, so we effectively need to support unwinding past them. Marking these nounwind is technically correct, but not compatible with how unwinding works in reality. Fixes llvm#61945. Differential Revision: https://reviews.llvm.org/D147694
Currently, FunctionAttrs treats landingpads as non-throwing, and will infer nounwind for functions with landingpads (assuming they can't unwind in some other way, e.g. via resum). There are two problems with this: * Non-cleanup landingpads with catch/filter clauses do not necessarily catch all exceptions. Unless there are catch ptr null or filter [0 x ptr] zeroinitializer clauses, we should assume that we may unwind past this landingpad. This seems like an outright bug. * Cleanup landingpads are skipped during phase one unwinding, so we effectively need to support unwinding past them. Marking these nounwind is technically correct, but not compatible with how unwinding works in reality. Fixes llvm/llvm-project#61945. Differential Revision: https://reviews.llvm.org/D147694
Consider the following example:
This should print "cleanup" followed by abort. Instead this happens when using Clang 17:
The reason for this is that we now (correctly) infer that
abort_in_dtor()
isnounwind
. However, as phase 1 unwind skips cleanups, this means that the unwind walk will try to go past anounwind
frame, which may not have an LSDA entry, resulting in some form of unwinding failure. (In this specific case we return_URC_END_OF_STACK
, but a similar case in Rust results in_URC_FATAL_PHASE1_ERROR
.)The text was updated successfully, but these errors were encountered: