-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Hook up std::net to wasi-libc on wasm32-wasip2 target #129638
base: master
Are you sure you want to change the base?
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @tgross35 (or someone else) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
Thanks for the PR! The reasoning for these changes makes sense, but why are all the extern interfaces added here? That part of the changes should go into our libc https://github.com/rust-lang/libc/blob/72cb7aaf50bf70b5d360b1a64b0d52d3ed3fbf15/src/wasi.rs. Pinging was[mi] expert @alexcrichton, could you double check the reasoning here? |
More specifically, if these are available on wasi-p2 but not p1 then the libc changes would mean:
|
I was planning to work on bringing those extern interfaces to rust-lang/libc next by doing exactly that. |
It would be better to update libc first so definitions only live in a single place, I would be concerned about things getting out of sync otherwise. Doing that shouldn't be much worse than adding them here - you can probably just do steps 1, 2, and 4 in my list above, skipping step 3 unless it turns out to be a problem. The turnaround is pretty quick getting a new libc version and updating std. |
Also if you have a link to the headers please post them in the libc PR, sometimes it's tough to track down where definitions came from |
Thanks so much for working on this! I'll do a review tomorrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for working on this! I've left some comments below with a few thoughts here and there. Mostly I'm hoping we can delegate to libc to return errors where possible instead of explicitly returning errors here since that'll make it easier to support in the future by just changing wasi-libc. Otherwise most of your other changes also makes sense to me, but let me know if you have any more questions.
As for libc
bindings, I agree it'd be great to get these bindings upstream into the libc
crate itself. I can try to take a look at setting that up CI-wise, and/or please feel free to cc me on PRs.
|
||
pub fn init() {} | ||
|
||
pub struct Socket(WasiFd); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The WASIp2 target is moving in a different direction than WASIp1 so one refactoring I've been meaning to do for awhile is to reduce the reliance on WasiFd
in the WASIp2 target. To that effect could you switch this to directly using a c_int
internally? That would require reproduction of the destruction and removal of the AsRef<WasiFd>
implementation but that accurately reflects how a socket works on this platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The WASI targets currently use the common implementation of std::os::fd
, which defines all sorts of traits to convert between (Owned|Borrowed|Raw)Fd
and Socket
and I'm not exactly sure what other parts of the std lib rely on the fact that you can convert between those types. I could try to add an implementation for WASIp2 without those traits. Just checking back that this is the path forward before I dive in and run into a dead end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm ok if it's difficult to do then it's fine to leave this in for now. The WASIp2 traits in this regard need to be improved and is something I should put on my plate of things-to-refactor for the future. My guess is that it's probably too much to take on in this PR, so feel free to defer it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had another look at this and I'm not sure this is possible at all without potentially breaking user's code since the trait implementations I mentioned aren't gated and can be used today. I could replace WasiFd
with OwnedFd
to at least decouple the socket-related from the file-related code if that's an acceptable compromise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's easy enough yeah OwnedFd
I think would be a better fit since we need to eventually sunset WasiFd
on the p2 target anyway. Again though feel free to defer to a future PR. The main thing I was worried about which was std::os::wasi
is already unstable on the p2 target, as desired, so what I was originally worried about is already taken care of.
I've started a bit with wasi-libc by submitting rust-lang/libc#3869 to re-enable CI. Once that's ready I'll also submit a new target of wasm32-wasip2 and get that configured/ready too. After that it should be a simpler to add p2-specific constants and such. |
Oh I can also mention, have you been able to test this? For example are you able to run perhaps the |
Thanks for the review and starting the work on libc. I'll have a look at moving over the brindings next. Unfortunately, building the standard library test suit for the |
You should be able to filter them with something like |
This is similar to rust-lang#3869 except that it adds tests for `wasm32-wasip2` in addition to `wasm32-wasip1`. This is intended to eventually empower definitions from rust-lang/rust#129638 to move into this repository.
This is similar to rust-lang#3869 except that it adds tests for `wasm32-wasip2` in addition to `wasm32-wasip1`. This is intended to eventually empower definitions from rust-lang/rust#129638 to move into this repository. (backport <rust-lang#3870>) (cherry picked from commit 15f8c44)
This is similar to rust-lang#3869 except that it adds tests for `wasm32-wasip2` in addition to `wasm32-wasip1`. This is intended to eventually empower definitions from rust-lang/rust#129638 to move into this repository. (backport <rust-lang#3870>) (cherry picked from commit 15f8c44)
Ok all looks good to me, thanks again! Before landing though I think it'd be good to run this through its paces with the test suite of the standard library (or another library if you're interested in another library perhaps?). If the standard library's tests don't build at all is it possible to temporarily comment out the pieces that don't build? This won't be run on CI anyway so it's more of a one-time check to make sure things are working. |
Are the bindings able to go into libc? I'm working on rolling a release today, happy to hold off on that. |
I'm working on the bindings right now. If you could hold off on the release, that'd be great. |
No problem! They're pretty quick to do whenever |
They fail to build. Here are the errors I'm getting: error: cannot find macro `error` in this scope
--> std/src/fs/tests.rs:1147:5
|
1147 | error!(blank.create(true).open(&tmpdir.join("f")), invalid_options);
| ^^^^^
error[E0433]: failed to resolve: could not find `unix` in `os`
--> std/src/process/tests.rs:574:16
|
574 | crate::os::unix::process::CommandExt::arg0(&mut command, "exciting-name");
| ^^^^ could not find `unix` in `os`
|
note: found an item that was configured out
--> std/src/os/mod.rs:27:9
|
27 | pub mod unix {}
| ^^^^
note: the item is gated here
--> std/src/os/mod.rs:19:1
|
19 | / #[cfg(all(
20 | | doc,
21 | | any(
22 | | all(target_arch = "wasm32", not(target_os = "wasi")),
23 | | all(target_vendor = "fortanix", target_env = "sgx")
24 | | )
25 | | ))]
| |___^
note: found an item that was configured out
--> std/src/os/mod.rs:65:9
|
65 | pub mod unix;
| ^^^^
note: the item is gated here
--> std/src/os/mod.rs:64:1
|
64 | #[cfg(all(not(target_os = "hermit"), any(unix, doc)))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0405]: cannot find trait `AsRawFd` in this scope
--> std/src/net/tcp/tests.rs:678:32
|
678 | fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
| ^^^^^^^ not found in this scope
|
help: consider importing one of these traits
|
1 + use crate::os::fd::AsRawFd;
|
1 + use crate::realstd::os::fd::AsRawFd;
|
error[E0425]: cannot find function `symlink_file` in this scope
--> std/src/fs/tests.rs:76:11
|
76 | match symlink_file(r"nonexisting_target", link) {
| ^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `junction_point` in this scope
--> std/src/fs/tests.rs:595:12
|
595 | check!(junction_point(&d2, &dt.join("d2")));
| ^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `symlink_dir` in this scope
--> std/src/fs/tests.rs:702:17
|
702 | let _ = symlink_dir(attack_dest_dir, &victim_del_path);
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `env_cmd` in this scope
--> std/src/process/tests.rs:276:19
|
276 | let mut cmd = env_cmd();
| ^^^^^^^ not found in this scope It looks like the standard library test suite expects the
I agree, that would be good! I can't think of a library to thoroughly test this with off the top of my head, but I'll look into getting the test suite to build 👍 |
Ah ok, thanks for the explanation! In that case I think it's ok to comment things out locally enough to get the |
Ah alas I forgot that many of the sockets-related tests all used threads as well. Were many able to be run under wasm32-wasip2? If not that's ok, but thanks for getting the tests compiling at least! |
Getting the tests to build turned out to be easier than I initially thought since those tests that expect either a
Yeah, there aren't many sockets-related tests left, unfortunately. But those that do not rely on threads are all running successfully (at least for me locally). With the last push, I also disabled network-related tests for WASIp1 and changed the default config for the wasi test runner to enable networking and allow IP name lookup. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks great to me, thanks again for doing the work on getting the libstd tests working!
@tgross35 do you have an opinion one way or another on landing this before or after a libc update in the workspace here? I don't have a strong feeling myself but if it's desired to not duplicate these libc definitions then I think the only remaining blocker is waiting on the libc update
Just checking whether my understanding of the state of this PR is correct. I believe what's needed is:
Does that sound right? |
@jeffparsons I'm not exactly sure if we have to wait for a weekly |
@tgross35 What's involved in getting a new libc release published? Is it just done periodically, done on request, or...? (Sorry if this is naggy — it just wasn't clear to me if the default for this sort of thing is meant to be "be patient" or "things only happen if asked". I am enthusiastically open to feedback on this! 🙇♂️) |
Sorry about that, it is indeed waiting on me :) I was waiting on a fix to get in that took a little while, now I just need to double check everything and actually do the release but haven't had time (I'll be back early next week, will be easier then).
No worries! I've been trying to do one every few PRs or whenever there is a logical group of changes. This one has been more or less at that point for a couple weeks, just got delayed by needing a fix. |
Done :) https://github.com/rust-lang/libc/releases/tag/0.2.159 The libc bump should be in its own PR, feel free to |
One of the improvements of the
wasm32-wasip2
target overwasm32-wasip1
is better support for networking. Right now, p2 is just re-using thestd::net
implementation from p1. This PR adds a new net module for p2 that makes use of net fromsys_common
and calls wasi-libc functions directly.There are currently a few limitations:
TCP_NODELAY
is faked in wasi-libc (uses the fake implementation instead of returning an error)SO_LINGER
is not supported by WASIp2 (directly returns an error)SO_REUSEADDR
is faked in wasi-libc (since this is done fromsys_common
, the fake implementation is used instead of returning an error)IPV6_V6ONLY
is not supported by WASIp2 and will always be set for IPv6 sockets (since this is done fromsys_common
, wasi-libc will return an error)sys_common
, wasi-libc will return appropriate errors)MSG_NOSIGNAL
send flag is a no-op because there are no signals in WASIp2 (since explicitly setting this flag would require a change tosys_common
and the result would be exactly the same, I opted to not set it)Do those decisions make sense?
While working on this PR, I noticed that there is a
std::os::wasi::net::TcpListenerExt
trait that adds asock_accept()
method tostd::net::TcpListener
. Now that WASIp2 supports standard accept, would it make sense to remove this?cc @alexcrichton