Skip to content

Commit

Permalink
Rollup merge of rust-lang#129638 - nickrum:wasip2-net, r=alexcrichton
Browse files Browse the repository at this point in the history
Hook up std::net to wasi-libc on wasm32-wasip2 target

One of the improvements of the `wasm32-wasip2` target over `wasm32-wasip1` is better support for networking. Right now, p2 is just re-using the `std::net` implementation from p1. This PR adds a new net module for p2 that makes use of net from `sys_common` and calls wasi-libc functions directly.

There are currently a few limitations:

- Duplicating a socket is not supported by WASIp2 (directly returns an error)
- Peeking is not yet implemented in wasi-libc (we could let wasi-libc handle this, but I opted to directly return an error instead)
- Vectored reads/writes are not supported by WASIp2 (the necessary functions are available in wasi-libc, but they call WASIp1 functions which do not support sockets, so I opted to directly return an error instead)
- Getting/setting `TCP_NODELAY` is faked in wasi-libc (uses the fake implementation instead of returning an error)
- Getting/setting `SO_LINGER` is not supported by WASIp2 (directly returns an error)
- Setting `SO_REUSEADDR` is faked in wasi-libc (since this is done from `sys_common`, the fake implementation is used instead of returning an error)
- Getting/setting `IPV6_V6ONLY` is not supported by WASIp2 and will always be set for IPv6 sockets (since this is done from `sys_common`, wasi-libc will return an error)
- UDP broadcast/multicast is not supported by WASIp2 (since this is configured from `sys_common`, wasi-libc will return appropriate errors)
- The `MSG_NOSIGNAL` send flag is a no-op because there are no signals in WASIp2 (since explicitly setting this flag would require a change to `sys_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 a `sock_accept()` method to `std::net::TcpListener`. Now that WASIp2 supports standard accept, would it make sense to remove this?

cc `@alexcrichton`
  • Loading branch information
tgross35 authored Sep 30, 2024
2 parents b362019 + 9ae087c commit 99e9853
Show file tree
Hide file tree
Showing 32 changed files with 506 additions and 47 deletions.
3 changes: 3 additions & 0 deletions std/src/collections/hash/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@ mod test_extract_if {
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn drop_panic_leak() {
static PREDS: AtomicUsize = AtomicUsize::new(0);
static DROPS: AtomicUsize = AtomicUsize::new(0);
Expand Down Expand Up @@ -1047,6 +1048,7 @@ mod test_extract_if {
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn pred_panic_leak() {
static PREDS: AtomicUsize = AtomicUsize::new(0);
static DROPS: AtomicUsize = AtomicUsize::new(0);
Expand Down Expand Up @@ -1076,6 +1078,7 @@ mod test_extract_if {

// Same as above, but attempt to use the iterator again after the panic in the predicate
#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn pred_panic_reuse() {
static PREDS: AtomicUsize = AtomicUsize::new(0);
static DROPS: AtomicUsize = AtomicUsize::new(0);
Expand Down
2 changes: 2 additions & 0 deletions std/src/collections/hash/set/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ fn test_extract_if() {
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_extract_if_drop_panic_leak() {
static PREDS: AtomicU32 = AtomicU32::new(0);
static DROPS: AtomicU32 = AtomicU32::new(0);
Expand Down Expand Up @@ -459,6 +460,7 @@ fn test_extract_if_drop_panic_leak() {
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_extract_if_pred_panic_leak() {
static PREDS: AtomicU32 = AtomicU32::new(0);
static DROPS: AtomicU32 = AtomicU32::new(0);
Expand Down
2 changes: 1 addition & 1 deletion std/src/env/tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

#[test]
#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"), ignore)]
fn test_self_exe_path() {
let path = current_exe();
assert!(path.is_ok());
Expand Down
10 changes: 9 additions & 1 deletion std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@
#![stable(feature = "rust1", since = "1.0.0")]
#![deny(unsafe_op_in_unsafe_fn)]

#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx", target_os = "xous"))))]
#[cfg(all(
test,
not(any(
target_os = "emscripten",
target_os = "wasi",
target_env = "sgx",
target_os = "xous"
))
))]
mod tests;

use crate::ffi::OsString;
Expand Down
3 changes: 2 additions & 1 deletion std/src/io/buffered/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ fn test_buffered_reader_stream_position() {
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_buffered_reader_stream_position_panic() {
let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
let mut reader = BufReader::with_capacity(4, io::Cursor::new(inner));
Expand Down Expand Up @@ -487,7 +488,7 @@ fn dont_panic_in_drop_on_panicked_flush() {
}

#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
fn panic_in_write_doesnt_flush_in_drop() {
static WRITES: AtomicUsize = AtomicUsize::new(0);

Expand Down
8 changes: 4 additions & 4 deletions std/src/io/stdio/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn stderrlock_unwind_safe() {
fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}

#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
fn panic_doesnt_poison() {
thread::spawn(|| {
let _a = stdin();
Expand All @@ -48,17 +48,17 @@ fn panic_doesnt_poison() {
}

#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
fn test_lock_stderr() {
test_lock(stderr, || stderr().lock());
}
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
fn test_lock_stdin() {
test_lock(stdin, || stdin().lock());
}
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
fn test_lock_stdout() {
test_lock(stdout, || stdout().lock());
}
Expand Down
2 changes: 1 addition & 1 deletion std/src/net/ip_addr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Tests for this module
#[cfg(all(test, not(target_os = "emscripten")))]
#[cfg(all(test, not(any(target_os = "emscripten", all(target_os = "wasi", target_env = "p1")))))]
mod tests;

#[stable(feature = "ip_addr", since = "1.7.0")]
Expand Down
2 changes: 1 addition & 1 deletion std/src/net/socket_addr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Tests for this module
#[cfg(all(test, not(target_os = "emscripten")))]
#[cfg(all(test, not(any(target_os = "emscripten", all(target_os = "wasi", target_env = "p1")))))]
mod tests;

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
9 changes: 8 additions & 1 deletion std/src/net/tcp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#![deny(unsafe_op_in_unsafe_fn)]

#[cfg(all(test, not(any(target_os = "emscripten", target_os = "xous"))))]
#[cfg(all(
test,
not(any(
target_os = "emscripten",
all(target_os = "wasi", target_env = "p1"),
target_os = "xous"
))
))]
mod tests;

use crate::fmt;
Expand Down
29 changes: 27 additions & 2 deletions std/src/net/tcp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ fn connect_timeout_error() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn listen_localhost() {
let socket_addr = next_test_ip4();
let listener = t!(TcpListener::bind(&socket_addr));
Expand All @@ -73,6 +74,7 @@ fn listen_localhost() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn connect_loopback() {
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
Expand All @@ -94,6 +96,7 @@ fn connect_loopback() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn smoke_test() {
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
Expand All @@ -114,6 +117,7 @@ fn smoke_test() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn read_eof() {
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
Expand All @@ -133,6 +137,7 @@ fn read_eof() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn write_close() {
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -161,6 +166,7 @@ fn write_close() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn multiple_connect_serial() {
each_ip(&mut |addr| {
let max = 10;
Expand All @@ -183,6 +189,7 @@ fn multiple_connect_serial() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn multiple_connect_interleaved_greedy_schedule() {
const MAX: usize = 10;
each_ip(&mut |addr| {
Expand Down Expand Up @@ -220,6 +227,7 @@ fn multiple_connect_interleaved_greedy_schedule() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn multiple_connect_interleaved_lazy_schedule() {
const MAX: usize = 10;
each_ip(&mut |addr| {
Expand Down Expand Up @@ -255,6 +263,7 @@ fn multiple_connect_interleaved_lazy_schedule() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn socket_and_peer_name() {
each_ip(&mut |addr| {
let listener = t!(TcpListener::bind(&addr));
Expand All @@ -270,6 +279,7 @@ fn socket_and_peer_name() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn partial_read() {
each_ip(&mut |addr| {
let (tx, rx) = channel();
Expand All @@ -291,6 +301,7 @@ fn partial_read() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn read_buf() {
each_ip(&mut |addr| {
let srv = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -389,6 +400,7 @@ fn double_bind() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn tcp_clone_smoke() {
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -420,6 +432,7 @@ fn tcp_clone_smoke() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn tcp_clone_two_read() {
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -454,6 +467,7 @@ fn tcp_clone_two_read() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn tcp_clone_two_write() {
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -483,6 +497,7 @@ fn tcp_clone_two_write() {
#[test]
// FIXME: https://github.com/fortanix/rust-sgx/issues/110
#[cfg_attr(target_env = "sgx", ignore)]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn shutdown_smoke() {
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
Expand All @@ -505,6 +520,7 @@ fn shutdown_smoke() {
#[test]
// FIXME: https://github.com/fortanix/rust-sgx/issues/110
#[cfg_attr(target_env = "sgx", ignore)]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn close_readwrite_smoke() {
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -547,6 +563,7 @@ fn close_readwrite_smoke() {
#[cfg_attr(target_env = "sgx", ignore)]
// On windows, shutdown will not wake up blocking I/O operations.
#[cfg_attr(windows, ignore)]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn close_read_wakes_up() {
each_ip(&mut |addr| {
let listener = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -574,6 +591,7 @@ fn close_read_wakes_up() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn clone_while_reading() {
each_ip(&mut |addr| {
let accept = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -614,6 +632,7 @@ fn clone_while_reading() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn clone_accept_smoke() {
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
Expand All @@ -632,6 +651,7 @@ fn clone_accept_smoke() {
}

#[test]
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn clone_accept_concurrent() {
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -670,10 +690,10 @@ fn debug() {
addr.to_string()
}

#[cfg(any(unix, target_os = "wasi"))]
use crate::os::fd::AsRawFd;
#[cfg(target_env = "sgx")]
use crate::os::fortanix_sgx::io::AsRawFd;
#[cfg(unix)]
use crate::os::unix::io::AsRawFd;
#[cfg(not(windows))]
fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
addr.as_raw_fd()
Expand Down Expand Up @@ -714,6 +734,7 @@ fn debug() {
ignore
)]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
#[test]
fn timeouts() {
let addr = next_test_ip4();
Expand Down Expand Up @@ -742,6 +763,7 @@ fn timeouts() {

#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
fn test_read_timeout() {
let addr = next_test_ip4();
let listener = t!(TcpListener::bind(&addr));
Expand All @@ -763,6 +785,7 @@ fn test_read_timeout() {

#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
fn test_read_with_timeout() {
let addr = next_test_ip4();
let listener = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -810,6 +833,7 @@ fn test_timeout_zero_duration() {

#[test]
#[cfg_attr(target_env = "sgx", ignore)]
#[cfg_attr(target_os = "wasi", ignore)] // linger not supported
fn linger() {
let addr = next_test_ip4();
let _listener = t!(TcpListener::bind(&addr));
Expand Down Expand Up @@ -879,6 +903,7 @@ fn set_nonblocking() {

#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
#[cfg_attr(target_os = "wasi", ignore)] // no threads
fn peek() {
each_ip(&mut |addr| {
let (txdone, rxdone) = channel();
Expand Down
10 changes: 9 additions & 1 deletion std/src/net/udp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx", target_os = "xous"))))]
#[cfg(all(
test,
not(any(
target_os = "emscripten",
all(target_os = "wasi", target_env = "p1"),
target_env = "sgx",
target_os = "xous"
))
))]
mod tests;

use crate::fmt;
Expand Down
Loading

0 comments on commit 99e9853

Please sign in to comment.