Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fill in some text #2

Merged
merged 7 commits into from
Oct 8, 2019
Merged

Fill in some text #2

merged 7 commits into from
Oct 8, 2019

Conversation

BatmanAoD
Copy link
Member

The new content is mostly based on the HackMD doc.

README.md Outdated
- [acfoltzer](https://github.com/acfoltzer)
- [batmanaod (Kyle)](https://github.com/batmanaod)
- with guidance/assistance from [nikmoatsakis](https://github.com/nikmoatsakis)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- with guidance/assistance from [nikmoatsakis](https://github.com/nikmoatsakis)
- with guidance/assistance from [Niko](https://github.com/nikmoatsakis)

I think having our "handles" and our names is probably a good idea, though I think that matters most in my case, where there's no clear connection between my name and my handle.

faq.md Outdated
@@ -0,0 +1,32 @@
## FAQ questions

- Why use a new ABI? Why not an attribute?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting nit: I think let's use ### headings (this also means people can link to the questions)

@nikomatsakis nikomatsakis merged commit 604321c into rust-lang:master Oct 8, 2019
Copy link
Contributor

@gnzlbg gnzlbg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setjmp/longjmp section looks good but there are some minor issues open.

Also, I'm not sure that the claim that drop is always guaranteed to run in some platforms is true. I recall that on MSVC whether objects are drop on a longjmp depends on whether a function is inlined or not. For example, if you have something like:

fn foo() {
   if setjmp(jmpbuf) == 0 {
       bar()     
   }
}
fn bar() {
   let x: DropT;
   baz()
}
fn baz() { longjmp(jmpbuf, 1) }

and bar is not inlined, then the destructor of bar::x will run because the bar function is unwound by the longjmp implementation. However, if bar is inlined into foo, the longjmp does not unwind over the cleanup code of bar::x because it will be somewhere in foos stack frame, and that stack frame is not unwound, so the destructor for bar::x does not run.

### How does cross-language unwinding differ from cross-language
`setjmp`/`longjmp`?
- `setjmp`/`longjmp` across Rust frames is currently guaranteed not to have
undefined behavior or to `abort`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a weird way to say that the behavior of setjmp/longjmp is defined. Maybe just explain how their behavior is defined instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Not undefined" is not equivalent to "is defined"; this is an (arguably unfortunate) legacy of the C/C++ ISO standards. Nico and I agree that Rust needs to better specify how "unspecified", "undefined", "implementation defined", etc are to be used in the Rust Reference and elsewhere in the Rust community, but at the moment, I felt that this was the safest phrasing, because "undefined behavior" is (ironically) the best-defined phrase at hand, as far as I can tell.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but what I'm saying is that the behavior of setjmp and longjmp in Rust is actually defined.

- It should never be assumed that `drop` will be called for objects in
intermediate frames traversed by a `longjmp`, but this may occur on certain
platforms. Rust provides no guarantee either way. Conversely, on platforms
where unwinding is supported, it will always call `drop`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this last sentence mean ? E.g. x86_64-unknown-linux-gnu is a platform where unwinding is supported, but longjmp never drops values living in stack frames. On other platforms like MSVC, do longjmps always drop values on stack frames?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, "it" here should have been "unwinding". You're right, this wasn't clear.

- `setjmp`/`longjmp` across Rust frames is currently guaranteed not to have
undefined behavior or to `abort`
- It should never be assumed that `drop` will be called for objects in
intermediate frames traversed by a `longjmp`, but this may occur on certain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If replacing a longjmp with a panic and a setjmp with a catch_unwind causes any destructors to run, the behavior is undefined. Some safe Rust abstractions like Pin rely on such things never happening.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, so much for my "safe" phrasing above! But this is sort of what I was worried about and why I don't want to just say that the behavior is defined. Wasn't it pointed out in one of the RFC threads that LLVM with the MSVC linker currently does generate code that causes longjmp to invoke destructors?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't it pointed out in one of the RFC threads that LLVM with the MSVC linker currently does generate code that causes longjmp to invoke destructors?

Since for the case being discussed the behavior is undefined, running destructors is one of the many things that could happen. Whatever LLVM does can change any time as a consequence of this, and IIRC whether destructors are run or not for particular functions depends on things like the optimization level.

where unwinding is supported, it will always call `drop`.
- Rust does not have a concept of `Copy` for stack-frames, which would permit
the compiler to check that `longjmp` may safely traverse those frames. Such a
language feature may be added in the future, but although it would be useful
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can point to Centril/rfc-effects#11 if you want to add more context about what that would entail.

the compiler to check that `longjmp` may safely traverse those frames. Such a
language feature may be added in the future, but although it would be useful
for `longjmp`, it would not be useful for unwinding.
- `setjmp`/`longjmp` does not involve data transfer (the exception object)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value of setjmp is a data-transfer from a longjmp.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, that's true. I'll modify it to say that the only possible value that can be transferred is c_int.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that you can use the return value of setjmp to transfer any kind of payload via the heap, just like we do for unwinding (the payload of panic is behind a Box<dyn Any + ...>), by doing a heap allocation before the longjmp and putting the pointer to it in a thread-local, that can be accessed from the setjmp.

for `longjmp`, it would not be useful for unwinding.
- `setjmp`/`longjmp` does not involve data transfer (the exception object)
- unwinding involves the use of a personality function, which raises additional
cross-language compatibility concerns; `setjmp`/`longjmp` does not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last sentence is unfinished.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I actually just wasn't consistent about putting periods at the end of bullet points.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So setjmp / longjmp have some requirements on how the language run-time works, e.g., the setjmp and longjmp must happen on the same thread, etc.

@BatmanAoD
Copy link
Member Author

... claim that drop is always guaranteed to run in some platforms is true.

I am guessing you are referring to the part where I used "it" ambiguously, and that my response there resolves this concern?

@gnzlbg
Copy link
Contributor

gnzlbg commented Oct 11, 2019

I am guessing you are referring to the part where I used "it" ambiguously, and that my response there resolves this concern?

Yes, that resolves it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants