From b1a8c03ef2c2df623b06c4225627991fdfb920be Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 30 Jun 2024 15:11:47 +0000 Subject: [PATCH] Add GNU/Hurd support --- .github/workflows/ci.yml | 1 + src/poll.rs | 4 ++++ src/sys/unix/mod.rs | 3 +++ src/sys/unix/net.rs | 3 +++ src/sys/unix/pipe.rs | 1 + src/sys/unix/tcp.rs | 1 + tests/poll.rs | 2 ++ tests/regressions.rs | 2 ++ tests/tcp.rs | 8 ++++++-- tests/tcp_stream.rs | 6 +++++- tests/udp_socket.rs | 26 +++++++++++++++++++++---- tests/unix_datagram.rs | 42 ++++++++++++++++++++++++++++------------ tests/unix_listener.rs | 2 ++ tests/unix_pipe.rs | 12 ++++++------ tests/unix_stream.rs | 38 ++++++++++++++++++++++++++++++++++++ 15 files changed, 126 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d661b85e..6e5426960 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -151,6 +151,7 @@ jobs: - arm64_32-apple-watchos - armv7-sony-vita-newlibeabihf - i686-unknown-linux-gnu + - i686-unknown-hurd-gnu - riscv32imc-esp-espidf - sparcv9-sun-solaris - wasm32-wasi diff --git a/src/poll.rs b/src/poll.rs index ee90b9153..b8b5cdf42 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -6,6 +6,7 @@ target_os = "fuchsia", target_os = "haiku", target_os = "hermit", + target_os = "hurd", target_os = "nto", target_os = "solaris", target_os = "vita" @@ -443,6 +444,7 @@ impl Poll { target_os = "fuchsia", target_os = "haiku", target_os = "hermit", + target_os = "hurd", target_os = "nto", target_os = "solaris", target_os = "vita" @@ -742,6 +744,7 @@ impl fmt::Debug for Registry { target_os = "haiku", target_os = "fuchsia", target_os = "hermit", + target_os = "hurd", target_os = "nto", target_os = "solaris", target_os = "vita" @@ -760,6 +763,7 @@ cfg_os_poll! { not(any( target_os = "espidf", target_os = "hermit", + target_os = "hurd", target_os = "nto", target_os = "solaris", target_os = "vita" diff --git a/src/sys/unix/mod.rs b/src/sys/unix/mod.rs index 92584d52b..b62238fb1 100644 --- a/src/sys/unix/mod.rs +++ b/src/sys/unix/mod.rs @@ -44,6 +44,7 @@ cfg_os_poll! { target_os = "fuchsia", target_os = "haiku", target_os = "hermit", + target_os = "hurd", target_os = "nto", target_os = "solaris", target_os = "vita", @@ -92,6 +93,7 @@ cfg_os_poll! { target_os = "aix", target_os = "dragonfly", target_os = "haiku", + target_os = "hurd", target_os = "netbsd", target_os = "nto", target_os = "openbsd", @@ -138,6 +140,7 @@ cfg_os_poll! { target_os = "aix", target_os = "dragonfly", target_os = "haiku", + target_os = "hurd", target_os = "netbsd", target_os = "nto", target_os = "openbsd", diff --git a/src/sys/unix/net.rs b/src/sys/unix/net.rs index 907e3b005..e6ffddeb5 100644 --- a/src/sys/unix/net.rs +++ b/src/sys/unix/net.rs @@ -17,6 +17,7 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R target_os = "android", target_os = "dragonfly", target_os = "freebsd", + target_os = "hurd", target_os = "illumos", target_os = "linux", target_os = "netbsd", @@ -116,6 +117,7 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_ target_os = "dragonfly", target_os = "freebsd", target_os = "haiku", + target_os = "hurd", target_os = "ios", target_os = "macos", target_os = "netbsd", @@ -151,6 +153,7 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_ target_os = "dragonfly", target_os = "freebsd", target_os = "haiku", + target_os = "hurd", target_os = "ios", target_os = "macos", target_os = "netbsd", diff --git a/src/sys/unix/pipe.rs b/src/sys/unix/pipe.rs index 8403c5e6e..3fc4f1575 100644 --- a/src/sys/unix/pipe.rs +++ b/src/sys/unix/pipe.rs @@ -13,6 +13,7 @@ pub(crate) fn new_raw() -> io::Result<[RawFd; 2]> { target_os = "dragonfly", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "linux", target_os = "netbsd", target_os = "openbsd", diff --git a/src/sys/unix/tcp.rs b/src/sys/unix/tcp.rs index 351beb4cb..f8dfa5817 100644 --- a/src/sys/unix/tcp.rs +++ b/src/sys/unix/tcp.rs @@ -69,6 +69,7 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream, target_os = "dragonfly", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "illumos", target_os = "linux", target_os = "netbsd", diff --git a/tests/poll.rs b/tests/poll.rs index 43d33fd5b..5a345e190 100644 --- a/tests/poll.rs +++ b/tests/poll.rs @@ -126,6 +126,8 @@ fn drop_cancels_interest_and_shuts_down() { let handle = thread::spawn(move || { let mut stream = listener.incoming().next().unwrap().unwrap(); + // SO_RCVTIMEO not supported on GNU/Hurd + #[cfg(not(target_os = "hurd"))] stream .set_read_timeout(Some(Duration::from_secs(5))) .expect("set_read_timeout"); diff --git a/tests/regressions.rs b/tests/regressions.rs index 0e3e5a9d8..bd880ff69 100644 --- a/tests/regressions.rs +++ b/tests/regressions.rs @@ -24,6 +24,8 @@ fn issue_776() { let handle = thread::spawn(move || { let mut stream = listener.accept().expect("accept").0; + // SO_RCVTIMEO not supported on GNU/Hurd + #[cfg(not(target_os = "hurd"))] stream .set_read_timeout(Some(Duration::from_secs(5))) .expect("set_read_timeout"); diff --git a/tests/tcp.rs b/tests/tcp.rs index 49e731936..46de0b40c 100644 --- a/tests/tcp.rs +++ b/tests/tcp.rs @@ -571,7 +571,7 @@ fn connect_error() { for event in &events { if event.token() == Token(0) { - assert!(event.is_writable()); + assert!(event.is_writable() || event.is_error()); // Solaris poll(2) says POLLHUP and POLLOUT are mutually exclusive. #[cfg(not(target_os = "solaris"))] assert!(event.is_write_closed()); @@ -702,7 +702,11 @@ fn write_shutdown() { socket.shutdown(Shutdown::Write).unwrap(); // POLLRDHUP isn't supported on Solaris, - if cfg!(any(target_os = "solaris", target_os = "nto")) { + if cfg!(any( + target_os = "hurd", + target_os = "solaris", + target_os = "nto" + )) { wait!(poll, is_readable, false); } else { wait!(poll, is_readable, true); diff --git a/tests/tcp_stream.rs b/tests/tcp_stream.rs index bbce14a19..9ff3c39f2 100644 --- a/tests/tcp_stream.rs +++ b/tests/tcp_stream.rs @@ -516,6 +516,7 @@ fn no_events_after_deregister() { windows, ignore = "fails on Windows; client read closed events are not triggered" )] +#[cfg_attr(target_os = "hurd", ignore = "POLLRDHUP isn't supported on GNU/Hurd")] #[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")] #[cfg_attr(target_os = "nto", ignore = "POLLRDHUP isn't supported on NTO")] fn tcp_shutdown_client_read_close_event() { @@ -553,6 +554,7 @@ fn tcp_shutdown_client_read_close_event() { #[cfg_attr( any( target_os = "android", + target_os = "hurd", target_os = "illumos", target_os = "solaris", target_os = "linux", @@ -591,6 +593,7 @@ fn tcp_shutdown_client_write_close_event() { } #[test] +#[cfg_attr(target_os = "hurd", ignore = "POLLRDHUP isn't supported on GNU/Hurd")] #[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")] #[cfg_attr(target_os = "nto", ignore = "POLLRDHUP isn't supported on NTO")] fn tcp_shutdown_server_write_close_event() { @@ -623,6 +626,7 @@ fn tcp_shutdown_server_write_close_event() { } #[test] +#[cfg_attr(target_os = "hurd", ignore = "POLLRDHUP isn't supported on GNU/Hurd")] #[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")] #[cfg_attr(target_os = "nto", ignore = "POLLRDHUP isn't supported on NTO")] fn tcp_reset_close_event() { @@ -673,7 +677,7 @@ fn tcp_reset_close_event() { ignore = "fails on Windows; client close events are not found" )] #[cfg_attr( - any(target_os = "illumos", target_os = "solaris"), + any(target_os = "hurd", target_os = "illumos", target_os = "solaris"), ignore = "fails; client write_closed events are not found" )] fn tcp_shutdown_client_both_close_event() { diff --git a/tests/udp_socket.rs b/tests/udp_socket.rs index ac82077ef..026329213 100644 --- a/tests/udp_socket.rs +++ b/tests/udp_socket.rs @@ -254,6 +254,10 @@ fn get_multicast_ttl_v4_without_previous_set() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "Multicast loop v6 isn't supported on GNU/Hurd" +)] fn set_get_multicast_loop_v6() { let socket1 = UdpSocket::bind(any_local_ipv6_address()).unwrap(); @@ -267,6 +271,10 @@ fn set_get_multicast_loop_v6() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "Multicast loop v6 isn't supported on GNU/Hurd" +)] fn get_multicast_loop_v6_without_previous_set() { let socket1 = UdpSocket::bind(any_local_ipv6_address()).unwrap(); @@ -553,7 +561,7 @@ fn unconnected_udp_socket_connected_methods() { ); // Socket is unconnected, but we're using an connected method. - if cfg!(not(target_os = "windows")) { + if cfg!(not(any(target_os = "hurd", target_os = "windows"))) { assert_error(socket1.send(DATA1), "address required"); } if cfg!(target_os = "windows") { @@ -616,12 +624,22 @@ fn connected_udp_socket_unconnected_methods() { ); // Can't use `send_to`. - // Linux (and Android) and Windows actually allow `send_to` even if the + // Linux (and Android) and GNU/Hurd Windows actually allow `send_to` even if the // socket is connected. - #[cfg(not(any(target_os = "android", target_os = "linux", target_os = "windows")))] + #[cfg(not(any( + target_os = "android", + target_os = "hurd", + target_os = "linux", + target_os = "windows" + )))] assert_error(socket1.send_to(DATA1, address2), "already connected"); // Even if the address is the same. - #[cfg(not(any(target_os = "android", target_os = "linux", target_os = "windows")))] + #[cfg(not(any( + target_os = "android", + target_os = "hurd", + target_os = "linux", + target_os = "windows" + )))] assert_error(socket1.send_to(DATA1, address3), "already connected"); checked_write!(socket2.send_to(DATA2, address3)); diff --git a/tests/unix_datagram.rs b/tests/unix_datagram.rs index 2345989b7..31da16c01 100644 --- a/tests/unix_datagram.rs +++ b/tests/unix_datagram.rs @@ -27,6 +27,10 @@ fn is_send_and_sync() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_datagram_smoke_unconnected() { init(); let path1 = temp_file("unix_datagram_smoke_unconnected1"); @@ -52,6 +56,10 @@ fn unix_datagram_smoke_connected() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_datagram_smoke_unconnected_from_std() { init(); let path1 = temp_file("unix_datagram_smoke_unconnected_from_std1"); @@ -89,6 +97,10 @@ fn unix_datagram_smoke_connected_from_std() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_datagram_connect() { init(); let path1 = temp_file("unix_datagram_connect1"); @@ -166,6 +178,7 @@ fn unix_datagram_pair() { } #[test] +#[cfg_attr(target_os = "hurd", ignore = "POLLRDHUP isn't supported on GNU/Hurd")] #[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")] #[cfg_attr(target_os = "nto", ignore = "POLLRDHUP isn't supported on NTO")] fn unix_datagram_shutdown() { @@ -285,6 +298,7 @@ fn smoke_test_unconnected(mut datagram1: UnixDatagram, mut datagram2: UnixDatagr assert_socket_non_blocking(&datagram2); assert_socket_close_on_exec(&datagram2); + // "getting pathname isn't supported on GNU/Hurd")] let addr1 = datagram1.local_addr().unwrap(); let addr2 = datagram2.local_addr().unwrap(); let path1 = addr1.as_pathname().expect("failed to get pathname"); @@ -343,18 +357,22 @@ fn smoke_test_connected(mut datagram1: UnixDatagram, mut datagram2: UnixDatagram assert_socket_non_blocking(&datagram2); assert_socket_close_on_exec(&datagram2); - let local_addr1 = datagram1.local_addr().unwrap(); - let peer_addr1 = datagram1.peer_addr().unwrap(); - let local_addr2 = datagram2.local_addr().unwrap(); - let peer_addr2 = datagram2.peer_addr().unwrap(); - assert_eq!( - local_addr1.as_pathname().expect("failed to get pathname"), - peer_addr2.as_pathname().expect("failed to get pathname") - ); - assert_eq!( - local_addr2.as_pathname().expect("failed to get pathname"), - peer_addr1.as_pathname().expect("failed to get pathname") - ); + // "getting pathname isn't supported on GNU/Hurd")] + #[cfg(not(target_os = "hurd"))] + { + let local_addr1 = datagram1.local_addr().unwrap(); + let peer_addr1 = datagram1.peer_addr().unwrap(); + let local_addr2 = datagram2.local_addr().unwrap(); + let peer_addr2 = datagram2.peer_addr().unwrap(); + assert_eq!( + local_addr1.as_pathname().expect("failed to get pathname"), + peer_addr2.as_pathname().expect("failed to get pathname") + ); + assert_eq!( + local_addr2.as_pathname().expect("failed to get pathname"), + peer_addr1.as_pathname().expect("failed to get pathname") + ); + } poll.registry() .register( diff --git a/tests/unix_listener.rs b/tests/unix_listener.rs index c13e9cbb6..ce62d4fb6 100644 --- a/tests/unix_listener.rs +++ b/tests/unix_listener.rs @@ -67,6 +67,8 @@ fn unix_listener_local_addr() { ); let (stream, expected_addr) = listener.accept().unwrap(); + // getting pathname isn't supported on GNU/Hurd + #[cfg(not(target_os = "hurd"))] assert_eq!(stream.local_addr().unwrap().as_pathname().unwrap(), &path); assert!(expected_addr.as_pathname().is_none()); diff --git a/tests/unix_pipe.rs b/tests/unix_pipe.rs index dc79026c4..73c28419a 100644 --- a/tests/unix_pipe.rs +++ b/tests/unix_pipe.rs @@ -54,8 +54,8 @@ fn smoke() { #[test] #[cfg_attr( - target_os = "nto", - ignore = "Writer fd close events do not trigger POLLHUP on nto target" + any(target_os = "hurd", target_os = "nto"), + ignore = "Writer fd close events do not trigger POLLHUP on nto and GNU/Hurd targets" )] fn event_when_sender_is_dropped() { let mut poll = Poll::new().unwrap(); @@ -96,8 +96,8 @@ fn event_when_sender_is_dropped() { #[test] #[cfg_attr( - target_os = "nto", - ignore = "Read fd close events do not trigger POLLHUP on nto target" + any(target_os = "hurd", target_os = "nto"), + ignore = "Writer fd close events do not trigger POLLHUP on nto and GNU/Hurd targets" )] fn event_when_receiver_is_dropped() { let mut poll = Poll::new().unwrap(); @@ -133,8 +133,8 @@ fn event_when_receiver_is_dropped() { #[test] #[cfg_attr( - target_os = "nto", - ignore = "Read/Write close eventsdo not trigger POLLHUP on nto target" + any(target_os = "hurd", target_os = "nto"), + ignore = "Writer fd close events do not trigger POLLHUP on nto and GNU/Hurd targets" )] fn from_child_process_io() { // `cat` simply echo everything that we write via standard in. diff --git a/tests/unix_stream.rs b/tests/unix_stream.rs index a501bae97..fda86bbc5 100644 --- a/tests/unix_stream.rs +++ b/tests/unix_stream.rs @@ -33,6 +33,10 @@ fn unix_stream_send_and_sync() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_smoke() { #[allow(clippy::redundant_closure)] smoke_test(|path| UnixStream::connect(path), "unix_stream_smoke"); @@ -78,6 +82,10 @@ fn unix_stream_connect() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_connect_addr() { let (mut poll, mut events) = init_with_poll(); let barrier = Arc::new(Barrier::new(2)); @@ -120,6 +128,10 @@ fn unix_stream_connect_addr() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_from_std() { smoke_test( |path| { @@ -167,6 +179,10 @@ fn unix_stream_pair() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_peer_addr() { init(); let (handle, expected_addr) = new_echo_listener(1, "unix_stream_peer_addr"); @@ -186,6 +202,7 @@ fn unix_stream_peer_addr() { } #[test] +#[cfg_attr(target_os = "hurd", ignore = "POLLRDHUP isn't supported on GNU/Hurd")] #[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")] #[cfg_attr(target_os = "nto", ignore = "POLLRDHUP isn't supported on NTO")] fn unix_stream_shutdown_read() { @@ -245,6 +262,10 @@ fn unix_stream_shutdown_read() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_shutdown_write() { let (mut poll, mut events) = init_with_poll(); let (handle, remote_addr) = new_echo_listener(1, "unix_stream_shutdown_write"); @@ -303,6 +324,10 @@ fn unix_stream_shutdown_write() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_shutdown_both() { let (mut poll, mut events) = init_with_poll(); let (handle, remote_addr) = new_echo_listener(1, "unix_stream_shutdown_both"); @@ -368,6 +393,7 @@ fn unix_stream_shutdown_both() { } #[test] +#[cfg_attr(target_os = "hurd", ignore = "POLLRDHUP isn't supported on GNU/Hurd")] #[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")] #[cfg_attr(target_os = "nto", ignore = "POLLRDHUP isn't supported on NTO")] fn unix_stream_shutdown_listener_write() { @@ -403,6 +429,10 @@ fn unix_stream_shutdown_listener_write() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_register() { let (mut poll, mut events) = init_with_poll(); let (handle, remote_addr) = new_echo_listener(1, "unix_stream_register"); @@ -420,6 +450,10 @@ fn unix_stream_register() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_reregister() { let (mut poll, mut events) = init_with_poll(); let (handle, remote_addr) = new_echo_listener(1, "unix_stream_reregister"); @@ -444,6 +478,10 @@ fn unix_stream_reregister() { } #[test] +#[cfg_attr( + target_os = "hurd", + ignore = "getting pathname isn't supported on GNU/Hurd" +)] fn unix_stream_deregister() { let (mut poll, mut events) = init_with_poll(); let (handle, remote_addr) = new_echo_listener(1, "unix_stream_deregister");