Stream: wg-ffi-unwind

Topic: Allow foreign exceptions to unwind through Rust code #65646


nikomatsakis (Oct 21 2019 at 20:28, on Zulip):

So @Amanieu has a PR that seems quite relevant to this working group =) I'm behind on our Zulip channels right now but I wanted to make sure we discussed it. At least based on the "main description" it sounds pretty great!

nikomatsakis (Oct 21 2019 at 20:30, on Zulip):

Description:

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.

Kyle Strand (Oct 21 2019 at 20:31, on Zulip):

Yes, Centril tagged me! I'll check it out. I meant to read the two RFC drafts yesterday but did not finish yet, unfortunately.

nikomatsakis (Oct 21 2019 at 20:31, on Zulip):

OK :)

Amanieu (Oct 22 2019 at 00:33, on Zulip):

Oh I didn't realize there was a WG for this. I only looked into this because @gnzlbg mentioned it to me.

Kyle Strand (Oct 22 2019 at 00:35, on Zulip):

@Amanieu Welcome! We plan to announce our existence...soon...ish.

Amanieu (Oct 28 2019 at 13:22, on Zulip):

I'm done with the PR. I've updated the description with details of the new behavior, so you can use it as a base for what to allow/disallow in this WG.

Amanieu (Oct 28 2019 at 13:22, on Zulip):

https://github.com/rust-lang/rust/pull/65646

gnzlbg (Oct 28 2019 at 13:36, on Zulip):

I think that there is quorum that allowing foreign exceptions to unwind through Rust code at some point would be ok

gnzlbg (Oct 28 2019 at 13:36, on Zulip):

The main controversy is whether one should be able to catch them or not from Rust @Amanieu

gnzlbg (Oct 28 2019 at 13:36, on Zulip):

That is, whether it should be possible to catch them at all, and if so, whether catch_unwind or something else

Amanieu (Oct 28 2019 at 13:36, on Zulip):

The main issue is that the signature of catch_unwind really isn't suited for returning a caught foreign exception.

gnzlbg (Oct 28 2019 at 13:37, on Zulip):

There is also the implementation issue of how should catch_unwind (or similar) deal with forced exceptions, etc.

gnzlbg (Oct 28 2019 at 13:37, on Zulip):

but yes, the signature is a big problem

Amanieu (Oct 28 2019 at 13:38, on Zulip):

Or longjmp exceptions on Windows.

gnzlbg (Oct 28 2019 at 13:38, on Zulip):

yes

gnzlbg (Oct 28 2019 at 13:38, on Zulip):

those aren't technically forced, but handling longjmp on windows differently would mean that longjmp behaves differently across platforms

gnzlbg (Oct 28 2019 at 13:38, on Zulip):

and a lot of code might want to rely on that not happening, but the truth is that longjmp does behave very differently across platforms

Amanieu (Oct 28 2019 at 13:39, on Zulip):

It already behaves differently across platforms: it only runs destructors on MSVC, not on MinGW or any non-Windows platform.

gnzlbg (Oct 28 2019 at 13:39, on Zulip):

yes

gnzlbg (Oct 28 2019 at 13:39, on Zulip):

My current opinion is that catch_unwind should ignore foreign exceptions always

gnzlbg (Oct 28 2019 at 13:39, on Zulip):

and If we want to add support for catching foreign exceptions, that should be a different API

Amanieu (Oct 28 2019 at 13:39, on Zulip):

IMO we should just do the same as C++ and say longjmp is UB if it unwinds through frames with destructors.

Amanieu (Oct 28 2019 at 13:40, on Zulip):

Yes I agree.

gnzlbg (Oct 28 2019 at 13:40, on Zulip):

the thing is that while C++ as a language says its UB, the implementations of C++ sometimes say "that is actually guaranteed to do X" (MSVC documents that longjmp runs destructors, and that's a guarantee there, so code for that platform can rely on that)

Amanieu (Oct 28 2019 at 13:41, on Zulip):

Actually MSVC documents that longjmp sometimes runs desctructors, depending on compiler options. And it has a big warning box saying that relying on this is nonportable.

gnzlbg (Oct 28 2019 at 13:41, on Zulip):

It also depends on noexcept, etc.

gnzlbg (Oct 28 2019 at 13:42, on Zulip):

MSVC documents that destructors of noexcept functions might or might not be run depending on the function being inlined

gnzlbg (Oct 28 2019 at 13:42, on Zulip):

but there is a long shot from that to "UB"

gnzlbg (Oct 28 2019 at 13:42, on Zulip):

I prefer to provide reasonables guarantees for the two types of unwinding that we have in general, the one that runs destructors, and the one that does not

gnzlbg (Oct 28 2019 at 13:43, on Zulip):

and then what longjmp does on platform X depends on how platform X implements longjmp

gnzlbg (Oct 28 2019 at 13:43, on Zulip):

but the language doesn't have to say anything about that

gnzlbg (Oct 28 2019 at 13:43, on Zulip):

(we want to probably document what each platform does)

Last update: Nov 15 2019 at 09:45UTC