Stream: project-ffi-unwind

Topic: longjmp rules


view this post on Zulip Connor Horman (Sep 28 2020 at 22:45):

I was attending the t-lang triage meeting earlier today, which reviewed this project, which I noted included longjmp.
I was wondering if it may be reasonable to adopt the same rules C++ has with longjmp and leave it at that.
The definition in C++ is that if you replace setjmp with try/catch, and longjmp with throw, the throw would execute a non-trivial destructor, the behaviour is undefined. Rust could make a similar requirement with catch_unwind and panic.

view this post on Zulip BatmanAoD (Kyle Strand) (Sep 28 2020 at 23:15):

@Connor Horman Thanks for asking. We have actually already formally defined the notion of non-trivial cleanup, in preparation for our longjmp specification, in the FFI-unwinding RFC: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md#plain-old-frames

view this post on Zulip BatmanAoD (Kyle Strand) (Sep 28 2020 at 23:16):

The reason we don't want to simply go ahead and say "longjmp is well defined across POFs" is that it actually inhibits an optimization that we are interested in.

view this post on Zulip BatmanAoD (Kyle Strand) (Sep 28 2020 at 23:18):

I thought it would be pretty easy to find our previous discussion about it, but apparently not... sorry! I've been meaning to write a blog post to kick off our longjmp-related work, so when I do, I'll be sure to dig up the conversation and include that information.

view this post on Zulip BatmanAoD (Kyle Strand) (Sep 28 2020 at 23:20):

The gist, if I remember correctly, was that we want to be able to re-order certain calls, and in some cases the re-ordering would cause UB if the function is canceled (e.g. w/ longjmp) in between the re-ordered calls, even if only POFs are involved.

view this post on Zulip BatmanAoD (Kyle Strand) (Sep 28 2020 at 23:23):

@Amanieu , my comment above wouldn't happen to ring any bells, would it?

view this post on Zulip Amanieu (Sep 29 2020 at 00:05):

You can search for longjmp in Zulip using the button at the top of the screen.

view this post on Zulip Amanieu (Sep 29 2020 at 00:05):

Maybe you're referring to the "UB to skip destructors" thread on zulip?

view this post on Zulip BatmanAoD (Kyle Strand) (Oct 08 2020 at 17:03):

@Amanieu you're correct, that's the thread! I was misled by looking at the first few posts in that thread; RalfJ brought up the optimization towards the end of the thread.

view this post on Zulip BatmanAoD (Kyle Strand) (Oct 08 2020 at 17:04):

@Connor Horman Here is the prior discussion about the optimization that can be enabled by prohibiting longjmp in some contexts: https://rust-lang.zulipchat.com/#narrow/stream/210922-project-ffi-unwind/topic/UB.20to.20skip.20destructors/near/200759346

view this post on Zulip BatmanAoD (Kyle Strand) (Oct 08 2020 at 17:04):

The other benefit of having an explicit annotation for cancelable functions is that the compiler can assist with ensuring that an entire stack is cancelable.

view this post on Zulip BatmanAoD (Kyle Strand) (Oct 08 2020 at 17:04):

By the way, our biweekly check-in is in half an hour, so feel free to drop in!

view this post on Zulip Amanieu (Apr 15 2021 at 14:42):

So apparently now that we emit noalias for &mut, LLVM will actually perform the store sinking optimization that gets broken by longjmp: https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=b0ac7b34a5bdc7c703247b8ab5dd6a9c

view this post on Zulip Amanieu (Apr 15 2021 at 14:44):

Interestingly, Clang does this too but GCC doesn't: https://godbolt.org/z/azj3K5zM1

view this post on Zulip Amanieu (Apr 15 2021 at 14:44):

(In all of these examples foo is marked as nounwind)

view this post on Zulip BatmanAoD (Kyle Strand) (Apr 15 2021 at 17:23):

That seems like it would be a miscompilation in LLVM, then?

view this post on Zulip BatmanAoD (Kyle Strand) (Apr 15 2021 at 17:24):

Since longjmp from foo to a caller of bar would end up having the wrong value in *x?

view this post on Zulip BatmanAoD (Kyle Strand) (Apr 15 2021 at 17:26):

I would personally be extremely chuffed if LLVM ends up introducing a new function attribute representing "longjmpable" or "non-longjmpable" that Rust is able to take advantage of

view this post on Zulip Amanieu (Apr 15 2021 at 21:44):

This only happens with restrict, which almost nobody uses.

view this post on Zulip Amanieu (Apr 15 2021 at 21:49):

I think it's a bug in LLVM: the transformation is invalid unless foo is guranteed to return. I think this would require the willreturn attribute, but I'm not 100% sure.

view this post on Zulip BatmanAoD (Kyle Strand) (Apr 15 2021 at 22:28):

Hm...I don't think we can use willreturn, though, if foo is not noexcept. If foo can unwind, I think this optimization would only be correct if the drop-glue (right term?) for bar could restore the correct value for x (by subtracting 1).

view this post on Zulip Amanieu (Apr 16 2021 at 01:51):

LLVM only performs this optimization if foo is nounwind. It doesn't touch the drop glue at all.

view this post on Zulip BatmanAoD (Kyle Strand) (Apr 16 2021 at 02:39):

Hm. Then yes, willreturn sounds appropriate for enabling this optimization.

view this post on Zulip BatmanAoD (Kyle Strand) (Apr 21 2021 at 16:57):

@Amanieu would you mind opening a bug report for this? If you're busy I can do it, but I think you probably understand the details better than I do.


Last updated: Jan 26 2022 at 09:02 UTC