You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Default behavior of unwinding in FFI functions #58794
This is the tracking issue for the behavior of unwinding through FFI functions.
There are two choices here: we can abort if unwinding occurs through an extern "C" boundary. We abort on beta 1.34 and nightly 1.35, but will permit unwinding in stable 1.33.
We previously attempted this change in 1.24 and reverted in 1.24.1. We attempted to do so again in 1.33, but reverted once again pending lang team discussion on the topic.
The stable behavior of permitting unwinding is UB, and can be triggered in safe code (#52652 (comment)). Notably, mozjpeg depends on this behavior and seems to have no good stable alternatives; there's been some discussion on internals.
It would be helpful for the discussion if someone knowledgeable could write a summary covering the following:
What are the issues with allowing unwinding through foreign languages on major platforms? What is the interaction with C++ exceptions? (Saying it's "UB" doesn't cut it)
What is the interaction between setjmp/longjmp and unwinding (in general, and on major platforms)?
Are there any concrete plans for writing a custom unwinder/"tweaking the unwinder"? Has anyone tried this/is anyone working on this? (The answer to this question may be used to determine how Rust restricts itself by locking into the standard unwinder on major platforms.)
When I say major platforms, I mean GNU libunwind, Windows SEH, possibly others.
Is it possible to have different default behavior depending on which unwinder you're using? Say, unwind normally on major platforms, abort on others?
What are the issues with allowing unwinding through foreign languages on major platforms? What is the interaction with C++ exceptions? (Saying it's "UB" doesn't cut it)
From a technical perspective this is pretty feasible, but from a stabilization perspective is historically something we've never wanted to provide. We want the technical freedom to tweak unwinding as we see fit, which means it's not guaranteed to match what C++ does across every single platform.
As for the current implementation, my understanding is: on Unix it works; on Windows it mostly works, with some issues that could be solved. See my comment in that thread for more details.
What is the interaction between setjmp/longjmp and unwinding (in general, and on major platforms)?
On Unix, longjmp just resets the stack pointer and ignores unwinding.
On Windows, longjmp triggers SEH unwinding and so will run Rust destructors, AFAIK. *
* (I said in other threads that it didn't, because I misread the description of this PR and thought that it changed things so destructors wouldn't run when unwinding via longjmp; in reality, it only did that to the abort-on-unwind handler itself.)
The current behavior on stable amounts to a soundness hole. For example, based on #52652 (comment), we can write (playground):
extern"C"fnbad(){panic!()}fnmain(){bad()}
The behavior of this program is undefined on stable because we attach the nounwind LLVM attribute to bad.
Soundness is non-negotiable and as such we landed #55982 to close this soundness hole. However, since there was no explicit confirmation of this step by the language team the change was reverted on 1.33 pending confirmation. The change is still seen in beta and nightly compilers.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
This change was tried twice, and twice it was reverted because important parts of the ecosystem broke. Do we really want to try merge it again without any changes?
The discussion on this topic is pretty fragmented, the internals thread mentioned in the top post has been quite active as well. I'm still waiting for the summary I requested #58794 (comment). I thought the scope of this issue is much bigger than what @Centril just mentioned. If you only care about the soundness issue at the IR level, another way to fix it is to never emit the nounwind attribute.
@joshtriplett I don't want to create a divide where there is none, but it seems to me that @gnzlbg is advocating to just stop emitting nounwind to LLVM altogether while we wait for a solution. I don't see them expressing an opinion on stabilizing (or removing) the unwind(allowed) attribute.
@BatmanAoD I would like to see your RFC continue, to develop a more precise specification of panic behavior. But I'd also like to see #[unwind(allowed)] stabilized more-or-less as-is, as soon as reasonably possible.
@jethrogb If we can't trivially get #[unwind(allowed)] stabilized, then I'm all for fixing the problem that way, but if we can get #[unwind(allowed)] stabilized quickly then let's do that.
Summarizing much further discussion: RFC 2699 is a much more general "how do we handle cross-language panics/unwinds/etc", while RFC 2753 is a much simpler proposal to just provide an #[unwind] attribute to disable nounwind and fix the UB.
So a lot has happened since this FCP was created. In RFC rust-lang/rfcs#2797, we created the ffi-unwind project group, for one thing. One of the first things we've been doing is debating this exact topic in some depth. Therefore, I'm going to cancel this FCP and close this issue -- we expect to try and resolve this issue very soon with a firmer decision about the direction we're going, and we'll re-evaluate in light of that.
Activity
jethrogb commentedon Feb 28, 2019
It would be helpful for the discussion if someone knowledgeable could write a summary covering the following:
When I say major platforms, I mean GNU libunwind, Windows SEH, possibly others.
Is it possible to have different default behavior depending on which unwinder you're using? Say, unwind normally on major platforms, abort on others?
comex commentedon Feb 28, 2019
In another thread, @alexcrichton wrote:
As for the current implementation, my understanding is: on Unix it works; on Windows it mostly works, with some issues that could be solved. See my comment in that thread for more details.
On Unix, longjmp just resets the stack pointer and ignores unwinding.
On Windows, longjmp triggers SEH unwinding and so will run Rust destructors, AFAIK. *
* (I said in other threads that it didn't, because I misread the description of this PR and thought that it changed things so destructors wouldn't run when unwinding via longjmp; in reality, it only did that to the abort-on-unwind handler itself.)
nagisa commentedon Feb 28, 2019
As far as the last part of that is concerned, that is an implementation-specific and unspecified behaviour.
Centril commentedon Mar 10, 2019
The current behavior on stable amounts to a soundness hole. For example, based on #52652 (comment), we can write (playground):
The behavior of this program is undefined on stable because we attach the
nounwindLLVM attribute tobad.Soundness is non-negotiable and as such we landed #55982 to close this soundness hole. However, since there was no explicit confirmation of this step by the language team the change was reverted on 1.33 pending confirmation. The change is still seen in beta and nightly compilers.
Based on notes by @alexcrichton in #52652 (comment), #55982 (comment), #55982 (comment), and #55982 (comment), I propose that we go ahead with and confirm the change in #55982.
@rfcbot merge
rfcbot commentedon Mar 10, 2019
Team member @Centril has proposed to merge this. The next step is review by the rest of the tagged team members:
Concerns:
blocked-on-rfc-2699resolved by Default behavior of unwinding in FFI functions #58794 (comment)Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
jethrogb commentedon Mar 10, 2019
This change was tried twice, and twice it was reverted because important parts of the ecosystem broke. Do we really want to try merge it again without any changes?
The discussion on this topic is pretty fragmented, the internals thread mentioned in the top post has been quite active as well. I'm still waiting for the summary I requested #58794 (comment). I thought the scope of this issue is much bigger than what @Centril just mentioned. If you only care about the soundness issue at the IR level, another way to fix it is to never emit the nounwind attribute.
Centril commentedon Mar 10, 2019
This is untrue. The second time it was reverted it was reverted only because of the lack of a completed T-Lang FCP (which we are doing now).
131 remaining items
jethrogb commentedon Jul 19, 2019
@joshtriplett I don't want to create a divide where there is none, but it seems to me that @gnzlbg is advocating to just stop emitting
nounwindto LLVM altogether while we wait for a solution. I don't see them expressing an opinion on stabilizing (or removing) theunwind(allowed)attribute.joshtriplett commentedon Jul 19, 2019
@BatmanAoD I would like to see your RFC continue, to develop a more precise specification of panic behavior. But I'd also like to see
#[unwind(allowed)]stabilized more-or-less as-is, as soon as reasonably possible.@jethrogb If we can't trivially get
#[unwind(allowed)]stabilized, then I'm all for fixing the problem that way, but if we can get#[unwind(allowed)]stabilized quickly then let's do that.BatmanAoD commentedon Jul 19, 2019
@joshtriplett Here is the tracking issue for stabilizing
#[unwind(allowed)]: #58760Permit unwinding through FFI by default
Auto merge of #62603 - cuviper:no-unwind-abort, r=joshtriplett
cuviper commentedon Aug 29, 2019
For those watching, @joshtriplett just proposed a simple
#[unwind]specification.joshtriplett commentedon Sep 9, 2019
@rfcbot resolved blocked-on-rfc-2699
@rfcbot concern blocked-on-rfc-2753
Summarizing much further discussion: RFC 2699 is a much more general "how do we handle cross-language panics/unwinds/etc", while RFC 2753 is a much simpler proposal to just provide an
#[unwind]attribute to disablenounwindand fix the UB.Permit unwinding through FFI by default
nikomatsakis commentedon Nov 22, 2019
@rfcbot fcp cancel
So a lot has happened since this FCP was created. In RFC rust-lang/rfcs#2797, we created the ffi-unwind project group, for one thing. One of the first things we've been doing is debating this exact topic in some depth. Therefore, I'm going to cancel this FCP and close this issue -- we expect to try and resolve this issue very soon with a firmer decision about the direction we're going, and we'll re-evaluate in light of that.
rfcbot commentedon Nov 22, 2019
@nikomatsakis proposal cancelled.
nikomatsakis commentedon Nov 22, 2019
If you'd like to participate in the group, btw, most of the discussion has been taking place in Zulip in the
#wg-ffi-unwindstream.