Skip to content

Default behavior of unwinding in FFI functions #58794

Description

@Mark-Simulacrum

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.

There has been discussion on this topic in #52652, #58760, and #55982.

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.

There is an RFC discussing this: rust-lang/rfcs#2699.

Activity

  1. added
    T-langRelevant to the language team
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Feb 28, 2019
  2. jethrogb commented on Feb 28, 2019

    @jethrogb
    Contributor

    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?

  3. comex commented on Feb 28, 2019

    @comex
    Contributor
    • 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)

    In another thread, @alexcrichton wrote:

    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.)

  4. nagisa commented on Feb 28, 2019

    @nagisa
    Member

    On Windows, longjmp triggers SEH unwinding and so will run Rust destructors

    As far as the last part of that is concerned, that is an implementation-specific and unspecified behaviour.

  5. Centril commented on Mar 10, 2019

    @Centril
    Contributor

    The current behavior on stable amounts to a soundness hole. For example, based on #52652 (comment), we can write (playground):

    extern "C" fn bad() {
        panic!()
    }
    
    fn main() {
        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.

    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

  6. rfcbot commented on Mar 10, 2019

    @rfcbot

    Team member @Centril has proposed to merge this. The next step is review by the rest of the tagged team members:

    Concerns:

    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.

  7. added
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.
    on Mar 10, 2019
  8. jethrogb commented on Mar 10, 2019

    @jethrogb
    Contributor

    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.

  9. Centril commented on Mar 10, 2019

    @Centril
    Contributor

    This change was tried twice, and twice it was reverted because important parts of the ecosystem broke.

    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).

  10. 131 remaining items

  11. jethrogb commented on Jul 19, 2019

    @jethrogb
    Contributor

    @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.

  12. joshtriplett commented on Jul 19, 2019

    @joshtriplett
    Member

    @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.

  13. BatmanAoD commented on Jul 19, 2019

    @BatmanAoD
    Contributor

    @joshtriplett Here is the tracking issue for stabilizing #[unwind(allowed)]: #58760

  14. added a commit that references this issue on Aug 26, 2019
  15. cuviper commented on Aug 29, 2019

    @cuviper
    Member

    For those watching, @joshtriplett just proposed a simple #[unwind] specification.

  16. joshtriplett commented on Sep 9, 2019

    @joshtriplett
    Member

    @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 disable nounwind and fix the UB.

  17. nikomatsakis commented on Nov 22, 2019

    @nikomatsakis
    Contributor

    @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.

  18. rfcbot commented on Nov 22, 2019

    @rfcbot

    @nikomatsakis proposal cancelled.

  19. removed
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.
    on Nov 22, 2019
  20. nikomatsakis commented on Nov 22, 2019

    @nikomatsakis
    Contributor

    If you'd like to participate in the group, btw, most of the discussion has been taking place in Zulip in the #wg-ffi-unwind stream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-langRelevant to the language team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions