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

Deprecate vfork #1574

Merged
merged 1 commit into from
Nov 18, 2019
Merged

Deprecate vfork #1574

merged 1 commit into from
Nov 18, 2019

Conversation

Amanieu
Copy link
Member

@Amanieu Amanieu commented Oct 29, 2019

The compiler may generate incorrect code for vfork and setjmp because they are missing the #[returns_twice] attribute which is currently unstable (tracking issue). Since vfork is impossible to use safely, I propose deprecating it until #[returns_twice] is stable.

@rust-highfive
Copy link

r? @gnzlbg

(rust_highfive has picked a reviewer for you, use r? to override)

@gnzlbg
Copy link
Contributor

gnzlbg commented Oct 29, 2019

@Amanieu thank you for filling this PR.

Right now, because vfork is lacking the returns_twice attribute, the compiler might mis-compile user code in some cases. Do we have any reported mis-compilations (or MWEs) due to this that illustrate the issue?

Claiming that this feature is impossible to use correctly won't do much for users that are already using vfork, because if it works for them, then in their eyes, it can be used correctly, and also, there is no really an alternative available, so they will just turn the warning off.

So what do we want to achieve ?

I think the best we can do right now is document any known mis-compilations by filling an issue, and then use the deprecation warning to inform users that such known mis-compilations exist, and that there is a nightly feature that they can use to avoid them, but that they are kind of on their own for now.

Just telling them "don't use this" without telling them "what to use instead" produces a very frustrating user experience. If this is really always impossible to use correctly, we should at least point them to an issue that explains that in detail.

@Amanieu
Copy link
Member Author

Amanieu commented Oct 29, 2019

I haven't managed to create a miscompiling example, but essentially, if the compiler decides to perform tail call optimization in the vfork child, this will corrupt the entire stack frame for the parent as well.

@Amanieu
Copy link
Member Author

Amanieu commented Oct 29, 2019

Alternatively, the compiler could decide to share a single stack slot for 2 variables, one in the parent and one in the child since it "knows" that only one of the two branches is taken, not both.

@gnzlbg
Copy link
Contributor

gnzlbg commented Oct 30, 2019

I think maybe @comex had an actual mis compilation example for a lack of returns_twice attribute but I can find it. There is an issue open in the rfc repo for longjmp, maybe we could link there ? I'd prefer to avoid using the term "impossible", but I think the deprecation warning can be a bit longer and strongly suggest not to use this API and being clear that it is UB and that any new toolchain upgrade could break existing "working" code in subtle ways silently so using it is very dangerous.

@Amanieu
Copy link
Member Author

Amanieu commented Nov 7, 2019

I've managed to create a miscompilation example: https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=e192ab81e8d408fa9984f766e2356697

As you can see, variables modified in the vfork child cause unrelated variables in the parent to be modified.

@Amanieu
Copy link
Member Author

Amanieu commented Nov 7, 2019

However if you add #[ffi_returns_twice] then the issue no longer appears: https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=0de019e56b69aa048f3e0f5319cc187e

@Amanieu
Copy link
Member Author

Amanieu commented Nov 12, 2019

@gnzlbg ping?

@gnzlbg
Copy link
Contributor

gnzlbg commented Nov 13, 2019

This looks good to me @Amanieu. CI is red due to unrelated issues, but I'll merge it ASAP.

In the mean time, could you create an issue in this repo explaining the problem with those links, and add a link to it to the deprecation message ?

@Amanieu
Copy link
Member Author

Amanieu commented Nov 17, 2019

Added a reference to #1596 in the deprecation message.

@gnzlbg
Copy link
Contributor

gnzlbg commented Nov 17, 2019

Thanks, as soon as we get up bors working again for the repo I'll start merging PRs.

@gnzlbg
Copy link
Contributor

gnzlbg commented Nov 18, 2019

@bors: r+

@bors
Copy link
Contributor

bors commented Nov 18, 2019

📌 Commit 1f7352c has been approved by gnzlbg

bors added a commit that referenced this pull request Nov 18, 2019
Deprecate vfork

The compiler may generate incorrect code for `vfork` and `setjmp` because they are missing the `#[returns_twice]` attribute which is currently unstable ([tracking issue](rust-lang/rust#58314)). Since `vfork` is impossible to use safely, I propose deprecating it until `#[returns_twice]` is stable.
@bors
Copy link
Contributor

bors commented Nov 18, 2019

⌛ Testing commit 1f7352c with merge a13ad69...

@bors
Copy link
Contributor

bors commented Nov 18, 2019

☀️ Test successful - checks-cirrus-freebsd-10, checks-cirrus-freebsd-11, checks-cirrus-freebsd-12, status-azure
Approved by: gnzlbg
Pushing a13ad69 to master...

@sporksmith
Copy link

sporksmith commented Mar 22, 2023

For anyone else who finds themselves here from the "vfork is deprecated" documentation - I have a working proof-of-concept workaround that calls vfork and exec from inline assembly on Linux x86-64. https://github.com/sporksmith/dev-journal/blob/main/rust-vfork/src/main.rs

The idea is that since both are done in assembly, the Rust compiler doesn't see the second return.

Similarly, I think this could alternatively be done by calling out to a helper C function that calls vfork and exec.

EDIT: I started thinking about whether this could be generalized into a utility function... and then realized that posix_spawn already does that. So probably better to just use posix_spawn in most cases, as long as it supports the actions that would otherwise need to perform in between the vfork and the exec.

sporksmith added a commit to shadow/shadow that referenced this pull request Mar 24, 2023
Bare vfork + exec are tricky to use, since it's easy to accidentally
corrupt the parent process's state from the child process. It's also
unsupported in Rust (rust-lang/libc#1574,
rust-lang/libc#1596).

I think we could work around this in Rust by using inline assembly or a
C helper function to wrap the fork and exec, but `posix_spawn` basically
does that for us already.
@Amanieu Amanieu mentioned this pull request Mar 14, 2024
19 tasks
@Lilit0x Lilit0x mentioned this pull request Mar 17, 2024
@tgross35 tgross35 added this to the 1.0 milestone Aug 12, 2024
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.

6 participants