Switch from extern "C"
to extern "C-unwind"
#718
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Closes #678
Reverts #683
Joint work with @lionel-
Consider the following
This effectively gets called as something similar to this (but I'm oversimplifying a bit):
We can also write this in terms of frames
In other words, when a
Rf_error()
causes alongjmp
, we are forced to jump over the rest of the Rustcallback()
frame. This is undefined behavior, even though we immediately catch that longjmp inR_ToplevelExec()
in the next C frame. The fact that we have jumped over the rest of the Rustcallback()
is simplify undefined behavior, full stop.The exact result of this undefined behavior seems to be platform dependent. It seems to mostly still work on Unix, as seen by our Mac and Linux builds still working. But on Windows it crashes ark hard with Rust 1.84, and we think it is due to this new
extern "C"
feature whereDrop
methods try to run now rust-lang/rust#129582. In the above example, we think theDrop
method formsg
is expected to run, but we've longjmped pastcallback()
so it can't properly run, and this blows something up.The best description of this is this table:
https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html#abi-boundaries-and-unforced-unwinding.
We are currently in the combination of
panic=unwind
,"C"-like
, causingUnforced foreign unwind
to result inUB
.The goal of this PR is to move us to
"C-unwind"
, causingUnforced foreign unwind
to result inunwind
. This was introduced in Rust 1.71 https://blog.rust-lang.org/2023/07/13/Rust-1.71.0.html#c-unwind-abiWith
"C-unwind
, we still end up jumping over the rest ofcallback()
, but Rust now expects that this is possible, so I'm guessing it allows for this internally. So nowmsg
is simply "leaked" because itsDrop
method doesn't run (ThisDrop
behavior is also platform dependent, notably theDrop
does seem to still run on Windows, but not on Unix). Before this PR we knew it would be leaked, but now we think we have made the leak "defined behavior" to Rust.So the moral of the story here is to still be extremely careful with the closure supplied to
try_catch()
andtop_level_exec()
. If the closure longjmps, then you cannot expect any destructors to run, so the closures should only create PODs if possible. But we now believe that jumping over the smallcallback()
frame is now well defined.