Skip to content

Commit

Permalink
Add Solaris operating system support (#1724)
Browse files Browse the repository at this point in the history
  • Loading branch information
psumbera committed Nov 16, 2023
1 parent e80c3b2 commit f6a20da
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -152,7 +152,7 @@ jobs:
strategy:
fail-fast: false
matrix:
target: ["armv7-sony-vita-newlibeabihf"]
target: ["armv7-sony-vita-newlibeabihf", "sparcv9-sun-solaris", "x86_64-pc-solaris"]
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
Expand Down
20 changes: 16 additions & 4 deletions src/poll.rs
@@ -1,4 +1,8 @@
#[cfg(all(unix, not(mio_unsupported_force_poll_poll), not(target_os = "vita")))]
#[cfg(all(
unix,
not(mio_unsupported_force_poll_poll),
not(any(target_os = "solaris", target_os = "vita"))
))]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
use std::sync::atomic::{AtomicBool, Ordering};
Expand Down Expand Up @@ -423,7 +427,11 @@ impl Poll {
}
}

#[cfg(all(unix, not(mio_unsupported_force_poll_poll), not(target_os = "vita")))]
#[cfg(all(
unix,
not(mio_unsupported_force_poll_poll),
not(any(target_os = "solaris", target_os = "vita"))
))]
impl AsRawFd for Poll {
fn as_raw_fd(&self) -> RawFd {
self.registry.as_raw_fd()
Expand Down Expand Up @@ -710,7 +718,11 @@ impl fmt::Debug for Registry {
}
}

#[cfg(all(unix, not(mio_unsupported_force_poll_poll), not(target_os = "vita")))]
#[cfg(all(
unix,
not(mio_unsupported_force_poll_poll),
not(any(target_os = "solaris", target_os = "vita"))
))]
impl AsRawFd for Registry {
fn as_raw_fd(&self) -> RawFd {
self.selector.as_raw_fd()
Expand All @@ -721,7 +733,7 @@ cfg_os_poll! {
#[cfg(all(
unix,
not(mio_unsupported_force_poll_poll),
not(target_os = "vita"),
not(any(target_os = "solaris", target_os = "vita")),
))]
#[test]
pub fn as_raw_fd() {
Expand Down
2 changes: 2 additions & 0 deletions src/sys/mod.rs
Expand Up @@ -54,6 +54,7 @@ cfg_os_poll! {
#[cfg(unix)]
cfg_os_poll! {
mod unix;
#[allow(unused_imports)]
pub use self::unix::*;
}

Expand All @@ -76,6 +77,7 @@ cfg_not_os_poll! {
#[cfg(unix)]
cfg_any_os_ext! {
mod unix;
#[cfg(feature = "os-ext")]
pub use self::unix::SourceFd;
}

Expand Down
9 changes: 6 additions & 3 deletions src/sys/unix/mod.rs
Expand Up @@ -18,6 +18,7 @@ cfg_os_poll! {
pub(crate) use self::selector::{event, Event, Events, Selector};

mod sourcefd;
#[cfg(feature = "os-ext")]
pub use self::sourcefd::SourceFd;

mod waker;
Expand All @@ -34,7 +35,7 @@ cfg_os_poll! {

cfg_io_source! {
// Both `kqueue` and `epoll` don't need to hold any user space state.
#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "vita")))]
#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "solaris", target_os = "vita")))]
mod stateless_io_source {
use std::io;
use std::os::unix::io::RawFd;
Expand Down Expand Up @@ -87,10 +88,10 @@ cfg_os_poll! {
}
}

#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "vita")))]
#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "solaris",target_os = "vita")))]
pub(crate) use self::stateless_io_source::IoSourceState;

#[cfg(any(mio_unsupported_force_poll_poll, target_os = "vita"))]
#[cfg(any(mio_unsupported_force_poll_poll, target_os = "solaris", target_os = "vita"))]
pub(crate) use self::selector::IoSourceState;
}

Expand All @@ -105,6 +106,7 @@ cfg_os_poll! {
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "vita",
))]
pub(crate) mod pipe;
Expand All @@ -118,6 +120,7 @@ cfg_not_os_poll! {

cfg_any_os_ext! {
mod sourcefd;
#[cfg(feature = "os-ext")]
pub use self::sourcefd::SourceFd;
}
}
3 changes: 2 additions & 1 deletion src/sys/unix/net.rs
Expand Up @@ -21,6 +21,7 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
))]
let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;

Expand Down Expand Up @@ -149,7 +150,7 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_
sin6_len: 0,
#[cfg(target_os = "vita")]
sin6_vport: addr.port().to_be(),
#[cfg(target_os = "illumos")]
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
__sin6_src_id: 0,
};

Expand Down
6 changes: 4 additions & 2 deletions src/sys/unix/pipe.rs
Expand Up @@ -17,6 +17,7 @@ pub(crate) fn new_raw() -> io::Result<[RawFd; 2]> {
target_os = "openbsd",
target_os = "illumos",
target_os = "redox",
target_os = "solaris",
target_os = "vita",
))]
unsafe {
Expand Down Expand Up @@ -68,6 +69,7 @@ pub(crate) fn new_raw() -> io::Result<[RawFd; 2]> {
target_os = "tvos",
target_os = "watchos",
target_os = "espidf",
target_os = "solaris",
target_os = "vita",
)))]
compile_error!("unsupported target for `mio::unix::pipe`");
Expand Down Expand Up @@ -558,7 +560,7 @@ impl IntoRawFd for Receiver {
}
}

#[cfg(not(any(target_os = "illumos", target_os = "vita")))]
#[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "vita")))]
fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
let value = nonblocking as libc::c_int;
if unsafe { libc::ioctl(fd, libc::FIONBIO, &value) } == -1 {
Expand All @@ -568,7 +570,7 @@ fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
}
}

#[cfg(any(target_os = "illumos", target_os = "vita"))]
#[cfg(any(target_os = "illumos", target_os = "solaris", target_os = "vita"))]
fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
if flags < 0 {
Expand Down
14 changes: 11 additions & 3 deletions src/sys/unix/selector/mod.rs
Expand Up @@ -20,14 +20,22 @@ mod epoll;
))]
pub(crate) use self::epoll::{event, Event, Events, Selector};

#[cfg(any(mio_unsupported_force_poll_poll, target_os = "vita"))]
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
mod poll;

#[cfg(any(mio_unsupported_force_poll_poll, target_os = "vita"))]
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
pub(crate) use self::poll::{event, Event, Events, Selector};

cfg_io_source! {
#[cfg(any(mio_unsupported_force_poll_poll, target_os = "vita"))]
#[cfg(any(mio_unsupported_force_poll_poll, target_os = "solaris", target_os = "vita"))]
pub(crate) use self::poll::IoSourceState;
}

Expand Down
1 change: 1 addition & 0 deletions src/sys/unix/tcp.rs
Expand Up @@ -67,6 +67,7 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
))]
let stream = {
syscall!(accept4(
Expand Down
24 changes: 19 additions & 5 deletions src/sys/unix/waker.rs
Expand Up @@ -10,7 +10,7 @@
target_os = "watchos",
)
)),
not(target_os = "vita"),
not(any(target_os = "solaris", target_os = "vita")),
))]
mod fdbased {
#[cfg(all(
Expand Down Expand Up @@ -63,7 +63,7 @@ mod fdbased {
target_os = "watchos",
)
)),
not(target_os = "vita"),
not(any(target_os = "solaris", target_os = "vita")),
))]
pub use self::fdbased::Waker;

Expand Down Expand Up @@ -207,6 +207,7 @@ pub use self::kqueue::Waker;
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "vita",
))]
mod pipe {
Expand Down Expand Up @@ -253,7 +254,11 @@ mod pipe {
}
}

#[cfg(any(mio_unsupported_force_poll_poll, target_os = "vita"))]
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
pub fn ack_and_reset(&self) {
self.empty();
}
Expand Down Expand Up @@ -291,11 +296,16 @@ mod pipe {
target_os = "redox",
)
),
target_os = "solaris",
target_os = "vita",
))]
pub(crate) use self::pipe::WakerInternal;

#[cfg(any(mio_unsupported_force_poll_poll, target_os = "vita"))]
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
mod poll {
use crate::sys::Selector;
use crate::Token;
Expand All @@ -321,5 +331,9 @@ mod poll {
}
}

#[cfg(any(mio_unsupported_force_poll_poll, target_os = "vita"))]
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
pub use self::poll::Waker;
9 changes: 8 additions & 1 deletion tests/tcp.rs
Expand Up @@ -572,6 +572,8 @@ fn connect_error() {
for event in &events {
if event.token() == Token(0) {
assert!(event.is_writable());
// Solaris poll(2) says POLLHUP and POLLOUT are mutually exclusive.
#[cfg(not(target_os = "solaris"))]
assert!(event.is_write_closed());
break 'outer;
}
Expand Down Expand Up @@ -698,7 +700,12 @@ fn write_shutdown() {
// Now, shutdown the write half of the socket.
socket.shutdown(Shutdown::Write).unwrap();

wait!(poll, is_readable, true);
// POLLRDHUP isn't supported on Solaris
if cfg!(target_os = "solaris") {
wait!(poll, is_readable, false);
} else {
wait!(poll, is_readable, true);
}
}

struct MyHandler {
Expand Down
12 changes: 10 additions & 2 deletions tests/tcp_stream.rs
Expand Up @@ -514,6 +514,7 @@ fn no_events_after_deregister() {
windows,
ignore = "fails on Windows; client read closed events are not triggered"
)]
#[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")]
fn tcp_shutdown_client_read_close_event() {
let (mut poll, mut events) = init_with_poll();
let barrier = Arc::new(Barrier::new(2));
Expand Down Expand Up @@ -547,7 +548,12 @@ fn tcp_shutdown_client_read_close_event() {
#[test]
#[cfg_attr(windows, ignore = "fails; client write_closed events are not found")]
#[cfg_attr(
any(target_os = "android", target_os = "illumos", target_os = "linux"),
any(
target_os = "android",
target_os = "illumos",
target_os = "solaris",
target_os = "linux"
),
ignore = "fails; client write_closed events are not found"
)]
fn tcp_shutdown_client_write_close_event() {
Expand Down Expand Up @@ -581,6 +587,7 @@ fn tcp_shutdown_client_write_close_event() {
}

#[test]
#[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")]
fn tcp_shutdown_server_write_close_event() {
let (mut poll, mut events) = init_with_poll();
let barrier = Arc::new(Barrier::new(2));
Expand Down Expand Up @@ -611,6 +618,7 @@ fn tcp_shutdown_server_write_close_event() {
}

#[test]
#[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")]
fn tcp_reset_close_event() {
let (mut poll, mut events) = init_with_poll();

Expand Down Expand Up @@ -659,7 +667,7 @@ fn tcp_reset_close_event() {
ignore = "fails on Windows; client close events are not found"
)]
#[cfg_attr(
any(target_os = "illumos"),
any(target_os = "illumos", target_os = "solaris"),
ignore = "fails; client write_closed events are not found"
)]
fn tcp_shutdown_client_both_close_event() {
Expand Down
1 change: 1 addition & 0 deletions tests/unix_datagram.rs
Expand Up @@ -166,6 +166,7 @@ fn unix_datagram_pair() {
}

#[test]
#[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")]
fn unix_datagram_shutdown() {
let (mut poll, mut events) = init_with_poll();
let path1 = temp_file("unix_datagram_shutdown1");
Expand Down
4 changes: 4 additions & 0 deletions tests/unix_stream.rs
Expand Up @@ -186,6 +186,7 @@ fn unix_stream_peer_addr() {
}

#[test]
#[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")]
fn unix_stream_shutdown_read() {
let (mut poll, mut events) = init_with_poll();
let (handle, remote_addr) = new_echo_listener(1, "unix_stream_shutdown_read");
Expand Down Expand Up @@ -326,6 +327,8 @@ fn unix_stream_shutdown_both() {
);

stream.shutdown(Shutdown::Both).unwrap();
// Solaris never returns POLLHUP for sockets.
#[cfg(not(target_os = "solaris"))]
expect_events(
&mut poll,
&mut events,
Expand Down Expand Up @@ -361,6 +364,7 @@ fn unix_stream_shutdown_both() {
}

#[test]
#[cfg_attr(target_os = "solaris", ignore = "POLLRDHUP isn't supported on Solaris")]
fn unix_stream_shutdown_listener_write() {
let (mut poll, mut events) = init_with_poll();
let barrier = Arc::new(Barrier::new(2));
Expand Down

0 comments on commit f6a20da

Please sign in to comment.