diff options
author | Jeff Vander Stoep <jeffv@google.com> | 2023-02-16 15:24:49 +0100 |
---|---|---|
committer | Jeff Vander Stoep <jeffv@google.com> | 2023-02-16 15:24:49 +0100 |
commit | 61fa94f41808c820ca6be95f722a0ef6efdc2a35 (patch) | |
tree | 051937287f30fd49716ced0af7befbb00ec9d957 /src | |
parent | 544dbb293255736fdafcca00c99e6f4b293c706a (diff) | |
download | mio-61fa94f41808c820ca6be95f722a0ef6efdc2a35.tar.gz |
Upgrade mio to 0.8.6
This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update rust/crates/mio
For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
Test: TreeHugger
Change-Id: I5a8f9771f053ac1d65c11d2cd25dae4345a475d0
Diffstat (limited to 'src')
-rw-r--r-- | src/interest.rs | 38 | ||||
-rw-r--r-- | src/net/tcp/stream.rs | 2 | ||||
-rw-r--r-- | src/sys/unix/net.rs | 56 | ||||
-rw-r--r-- | src/sys/unix/pipe.rs | 11 | ||||
-rw-r--r-- | src/sys/unix/selector/epoll.rs | 21 | ||||
-rw-r--r-- | src/sys/unix/selector/kqueue.rs | 53 | ||||
-rw-r--r-- | src/sys/unix/selector/mod.rs | 8 | ||||
-rw-r--r-- | src/sys/unix/tcp.rs | 13 | ||||
-rw-r--r-- | src/sys/unix/udp.rs | 20 | ||||
-rw-r--r-- | src/sys/unix/uds/datagram.rs | 12 | ||||
-rw-r--r-- | src/sys/unix/uds/listener.rs | 25 | ||||
-rw-r--r-- | src/sys/unix/uds/stream.rs | 15 | ||||
-rw-r--r-- | src/sys/unix/waker.rs | 29 | ||||
-rw-r--r-- | src/sys/windows/iocp.rs | 17 | ||||
-rw-r--r-- | src/sys/windows/net.rs | 25 | ||||
-rw-r--r-- | src/sys/windows/tcp.rs | 13 | ||||
-rw-r--r-- | src/sys/windows/udp.rs | 31 |
17 files changed, 178 insertions, 211 deletions
diff --git a/src/interest.rs b/src/interest.rs index 0aa0bda..50d1bf0 100644 --- a/src/interest.rs +++ b/src/interest.rs @@ -20,18 +20,9 @@ pub struct Interest(NonZeroU8); const READABLE: u8 = 0b0001; const WRITABLE: u8 = 0b0010; // The following are not available on all platforms. -#[cfg_attr( - not(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos" - )), - allow(dead_code) -)] const AIO: u8 = 0b0100; -#[cfg_attr(not(target_os = "freebsd"), allow(dead_code))] const LIO: u8 = 0b1000; +const PRIORITY: u8 = 0b10000; impl Interest { /// Returns a `Interest` set representing readable interests. @@ -45,7 +36,7 @@ impl Interest { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] pub const AIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(AIO) }); @@ -53,6 +44,10 @@ impl Interest { #[cfg(target_os = "freebsd")] pub const LIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(LIO) }); + /// Returns a `Interest` set representing priority completion interests. + #[cfg(any(target_os = "linux", target_os = "android"))] + pub const PRIORITY: Interest = Interest(unsafe { NonZeroU8::new_unchecked(PRIORITY) }); + /// Add together two `Interest`. /// /// This does the same thing as the `BitOr` implementation, but is a @@ -104,15 +99,20 @@ impl Interest { (self.0.get() & WRITABLE) != 0 } - /// Returns true if `Interest` contains AIO readiness + /// Returns true if `Interest` contains AIO readiness. pub const fn is_aio(self) -> bool { (self.0.get() & AIO) != 0 } - /// Returns true if `Interest` contains LIO readiness + /// Returns true if `Interest` contains LIO readiness. pub const fn is_lio(self) -> bool { (self.0.get() & LIO) != 0 } + + /// Returns true if `Interest` contains priority readiness. + pub const fn is_priority(self) -> bool { + (self.0.get() & PRIORITY) != 0 + } } impl ops::BitOr for Interest { @@ -152,7 +152,7 @@ impl fmt::Debug for Interest { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] { if self.is_aio() { @@ -173,6 +173,16 @@ impl fmt::Debug for Interest { one = true } } + #[cfg(any(target_os = "linux", target_os = "android"))] + { + if self.is_priority() { + if one { + write!(fmt, " | ")? + } + write!(fmt, "PRIORITY")?; + one = true + } + } debug_assert!(one, "printing empty interests"); Ok(()) } diff --git a/src/net/tcp/stream.rs b/src/net/tcp/stream.rs index a7a9aa1..8a3f6a2 100644 --- a/src/net/tcp/stream.rs +++ b/src/net/tcp/stream.rs @@ -72,7 +72,7 @@ impl TcpStream { /// `ErrorKind::NotConnected` it means the stream is not yet connected, /// go back to step 3. If it returns an address it means the stream is /// connected, go to step 5. If another error is returned something - /// whent wrong. + /// went wrong. /// 5. Now the stream can be used. /// /// This may return a `WouldBlock` in which case the socket connection diff --git a/src/sys/unix/net.rs b/src/sys/unix/net.rs index 78f1387..2396ab9 100644 --- a/src/sys/unix/net.rs +++ b/src/sys/unix/net.rs @@ -20,43 +20,39 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R target_os = "illumos", target_os = "linux", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", ))] let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC; - // Gives a warning for platforms without SOCK_NONBLOCK. - #[allow(clippy::let_and_return)] - let socket = syscall!(socket(domain, socket_type, 0)); + let socket = syscall!(socket(domain, socket_type, 0))?; // Mimick `libstd` and set `SO_NOSIGPIPE` on apple systems. - #[cfg(target_vendor = "apple")] - let socket = socket.and_then(|socket| { - syscall!(setsockopt( - socket, - libc::SOL_SOCKET, - libc::SO_NOSIGPIPE, - &1 as *const libc::c_int as *const libc::c_void, - size_of::<libc::c_int>() as libc::socklen_t - )) - .map(|_| socket) - }); + #[cfg(any(target_os = "ios", target_os = "macos"))] + if let Err(err) = syscall!(setsockopt( + socket, + libc::SOL_SOCKET, + libc::SO_NOSIGPIPE, + &1 as *const libc::c_int as *const libc::c_void, + size_of::<libc::c_int>() as libc::socklen_t + )) { + let _ = syscall!(close(socket)); + return Err(err); + } // Darwin doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC. #[cfg(any(target_os = "ios", target_os = "macos"))] - let socket = socket.and_then(|socket| { - // For platforms that don't support flags in socket, we need to - // set the flags ourselves. - syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK)) - .and_then(|_| syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)).map(|_| socket)) - .map_err(|e| { - // If either of the `fcntl` calls failed, ensure the socket is - // closed and return the error. - let _ = syscall!(close(socket)); - e - }) - }); + { + if let Err(err) = syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK)) { + let _ = syscall!(close(socket)); + return Err(err); + } + if let Err(err) = syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)) { + let _ = syscall!(close(socket)); + return Err(err); + } + } - socket + Ok(socket) } /// A type with the same memory layout as `libc::sockaddr`. Used in converting Rust level @@ -96,7 +92,7 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_ target_os = "ios", target_os = "macos", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", ))] sin_len: 0, }; @@ -120,7 +116,7 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_ target_os = "ios", target_os = "macos", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", ))] sin6_len: 0, #[cfg(target_os = "illumos")] diff --git a/src/sys/unix/pipe.rs b/src/sys/unix/pipe.rs index 7a95b96..7b7e4db 100644 --- a/src/sys/unix/pipe.rs +++ b/src/sys/unix/pipe.rs @@ -176,7 +176,7 @@ pub fn new() -> io::Result<(Sender, Receiver)> { || libc::fcntl(*fd, libc::F_SETFD, libc::FD_CLOEXEC) != 0 { let err = io::Error::last_os_error(); - // Don't leak file descriptors. Can't handle error though. + // Don't leak file descriptors. Can't handle closing error though. let _ = libc::close(fds[0]); let _ = libc::close(fds[1]); return Err(err); @@ -188,19 +188,20 @@ pub fn new() -> io::Result<(Sender, Receiver)> { target_os = "android", target_os = "dragonfly", target_os = "freebsd", + target_os = "illumos", + target_os = "ios", target_os = "linux", + target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "ios", - target_os = "macos", - target_os = "illumos", target_os = "redox", )))] compile_error!("unsupported target for `mio::unix::pipe`"); - // Safety: we just initialised the `fds` above. + // SAFETY: we just initialised the `fds` above. let r = unsafe { Receiver::from_raw_fd(fds[0]) }; let w = unsafe { Sender::from_raw_fd(fds[1]) }; + Ok((w, r)) } diff --git a/src/sys/unix/selector/epoll.rs b/src/sys/unix/selector/epoll.rs index 1256663..1809a2b 100644 --- a/src/sys/unix/selector/epoll.rs +++ b/src/sys/unix/selector/epoll.rs @@ -1,6 +1,6 @@ use crate::{Interest, Token}; -use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLRDHUP}; +use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLPRI, EPOLLRDHUP}; use log::error; use std::os::unix::io::{AsRawFd, RawFd}; #[cfg(debug_assertions)] @@ -88,16 +88,11 @@ impl Selector { let timeout = timeout .map(|to| { - let to_ms = to.as_millis(); - // as_millis() truncates, so round up to 1 ms as the documentation says can happen. - // This avoids turning submillisecond timeouts into immediate returns unless the - // caller explicitly requests that by specifying a zero timeout. - let to_ms = to_ms - + if to_ms == 0 && to.subsec_nanos() != 0 { - 1 - } else { - 0 - }; + // `Duration::as_millis` truncates, so round up. This avoids + // turning sub-millisecond timeouts into a zero timeout, unless + // the caller explicitly requests that by specifying a zero + // timeout. + let to_ms = (to + Duration::from_nanos(999_999)).as_millis(); cmp::min(MAX_SAFE_TIMEOUT, to_ms) as libc::c_int }) .unwrap_or(-1); @@ -182,6 +177,10 @@ fn interests_to_epoll(interests: Interest) -> u32 { kind |= EPOLLOUT; } + if interests.is_priority() { + kind |= EPOLLPRI; + } + kind as u32 } diff --git a/src/sys/unix/selector/kqueue.rs b/src/sys/unix/selector/kqueue.rs index 0be4281..1eedec0 100644 --- a/src/sys/unix/selector/kqueue.rs +++ b/src/sys/unix/selector/kqueue.rs @@ -21,7 +21,7 @@ type Count = libc::size_t; // Type of the `filter` field in the `kevent` structure. #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] type Filter = libc::c_short; -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "ios", target_os = "macos"))] type Filter = i16; #[cfg(target_os = "netbsd")] type Filter = u32; @@ -29,7 +29,7 @@ type Filter = u32; // Type of the `flags` field in the `kevent` structure. #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] type Flags = libc::c_ushort; -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "ios", target_os = "macos"))] type Flags = u16; #[cfg(target_os = "netbsd")] type Flags = u32; @@ -63,15 +63,17 @@ pub struct Selector { impl Selector { pub fn new() -> io::Result<Selector> { - syscall!(kqueue()) - .and_then(|kq| syscall!(fcntl(kq, libc::F_SETFD, libc::FD_CLOEXEC)).map(|_| kq)) - .map(|kq| Selector { - #[cfg(debug_assertions)] - id: NEXT_ID.fetch_add(1, Ordering::Relaxed), - kq, - #[cfg(debug_assertions)] - has_waker: AtomicBool::new(false), - }) + let kq = syscall!(kqueue())?; + let selector = Selector { + #[cfg(debug_assertions)] + id: NEXT_ID.fetch_add(1, Ordering::Relaxed), + kq, + #[cfg(debug_assertions)] + has_waker: AtomicBool::new(false), + }; + + syscall!(fcntl(kq, libc::F_SETFD, libc::FD_CLOEXEC))?; + Ok(selector) } pub fn try_clone(&self) -> io::Result<Selector> { @@ -403,7 +405,7 @@ pub mod event { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] { event.filter == libc::EVFILT_AIO @@ -412,7 +414,7 @@ pub mod event { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", )))] { false @@ -448,7 +450,7 @@ pub mod event { target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::EVFILT_FS, #[cfg(target_os = "freebsd")] @@ -457,7 +459,7 @@ pub mod event { target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::EVFILT_USER, #[cfg(target_os = "freebsd")] @@ -514,49 +516,49 @@ pub mod event { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::NOTE_TRIGGER, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::NOTE_FFNOP, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::NOTE_FFAND, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::NOTE_FFOR, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::NOTE_FFCOPY, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::NOTE_FFCTRLMASK, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "macos" + target_os = "macos", ))] libc::NOTE_FFLAGSMASK, libc::NOTE_LOWAT, @@ -591,21 +593,21 @@ pub mod event { target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", ))] libc::NOTE_TRACK, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", ))] libc::NOTE_TRACKERR, #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", ))] libc::NOTE_CHILD, #[cfg(any(target_os = "ios", target_os = "macos"))] @@ -633,7 +635,6 @@ pub mod event { #[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))] libc::NOTE_NSECONDS, #[cfg(any(target_os = "ios", target_os = "macos"))] - #[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))] libc::NOTE_ABSOLUTE, #[cfg(any(target_os = "ios", target_os = "macos"))] libc::NOTE_LEEWAY, diff --git a/src/sys/unix/selector/mod.rs b/src/sys/unix/selector/mod.rs index 9ae4c14..c06c7b1 100644 --- a/src/sys/unix/selector/mod.rs +++ b/src/sys/unix/selector/mod.rs @@ -17,20 +17,20 @@ pub(crate) use self::epoll::{event, Event, Events, Selector}; #[cfg(any( target_os = "dragonfly", target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", target_os = "ios", target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" ))] mod kqueue; #[cfg(any( target_os = "dragonfly", target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", target_os = "ios", target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" ))] pub(crate) use self::kqueue::{event, Event, Events, Selector}; diff --git a/src/sys/unix/tcp.rs b/src/sys/unix/tcp.rs index c4d7e94..9513cc0 100644 --- a/src/sys/unix/tcp.rs +++ b/src/sys/unix/tcp.rs @@ -40,7 +40,7 @@ pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()> } pub(crate) fn set_reuseaddr(socket: &net::TcpListener, reuseaddr: bool) -> io::Result<()> { - let val: libc::c_int = if reuseaddr { 1 } else { 0 }; + let val: libc::c_int = i32::from(reuseaddr); syscall!(setsockopt( socket.as_raw_fd(), libc::SOL_SOCKET, @@ -60,16 +60,13 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream, #[cfg(any( // Android x86's seccomp profile forbids calls to `accept4(2)` // See https://github.com/tokio-rs/mio/issues/1445 for details - all( - not(target_arch="x86"), - target_os = "android" - ), + all(not(target_arch="x86"), target_os = "android"), target_os = "dragonfly", target_os = "freebsd", target_os = "illumos", target_os = "linux", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", ))] let stream = { syscall!(accept4( @@ -85,10 +82,10 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream, // OSes inherit the non-blocking flag from the listener, so we just have to // set `CLOEXEC`. #[cfg(any( - all(target_arch = "x86", target_os = "android"), target_os = "ios", target_os = "macos", - target_os = "redox" + target_os = "redox", + all(target_arch = "x86", target_os = "android"), ))] let stream = { syscall!(accept( diff --git a/src/sys/unix/udp.rs b/src/sys/unix/udp.rs index 5a97cbd..843ae88 100644 --- a/src/sys/unix/udp.rs +++ b/src/sys/unix/udp.rs @@ -6,21 +6,13 @@ use std::net::{self, SocketAddr}; use std::os::unix::io::{AsRawFd, FromRawFd}; pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> { - // Gives a warning for non Apple platforms. - #[allow(clippy::let_and_return)] - let socket = new_ip_socket(addr, libc::SOCK_DGRAM); + let fd = new_ip_socket(addr, libc::SOCK_DGRAM)?; + let socket = unsafe { net::UdpSocket::from_raw_fd(fd) }; - socket.and_then(|socket| { - let (raw_addr, raw_addr_length) = socket_addr(&addr); - syscall!(bind(socket, raw_addr.as_ptr(), raw_addr_length)) - .map_err(|err| { - // Close the socket if we hit an error, ignoring the error - // from closing since we can't pass back two errors. - let _ = unsafe { libc::close(socket) }; - err - }) - .map(|_| unsafe { net::UdpSocket::from_raw_fd(socket) }) - }) + let (raw_addr, raw_addr_length) = socket_addr(&addr); + syscall!(bind(fd, raw_addr.as_ptr(), raw_addr_length))?; + + Ok(socket) } pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> { diff --git a/src/sys/unix/uds/datagram.rs b/src/sys/unix/uds/datagram.rs index d3e5314..a5ada72 100644 --- a/src/sys/unix/uds/datagram.rs +++ b/src/sys/unix/uds/datagram.rs @@ -7,18 +7,18 @@ use std::os::unix::net; use std::path::Path; pub(crate) fn bind(path: &Path) -> io::Result<net::UnixDatagram> { - let fd = new_socket(libc::AF_UNIX, libc::SOCK_DGRAM)?; - // Ensure the fd is closed. - let socket = unsafe { net::UnixDatagram::from_raw_fd(fd) }; let (sockaddr, socklen) = socket_addr(path)?; let sockaddr = &sockaddr as *const libc::sockaddr_un as *const _; - syscall!(bind(fd, sockaddr, socklen))?; + + let socket = unbound()?; + syscall!(bind(socket.as_raw_fd(), sockaddr, socklen))?; + Ok(socket) } pub(crate) fn unbound() -> io::Result<net::UnixDatagram> { - new_socket(libc::AF_UNIX, libc::SOCK_DGRAM) - .map(|socket| unsafe { net::UnixDatagram::from_raw_fd(socket) }) + let fd = new_socket(libc::AF_UNIX, libc::SOCK_DGRAM)?; + Ok(unsafe { net::UnixDatagram::from_raw_fd(fd) }) } pub(crate) fn pair() -> io::Result<(net::UnixDatagram, net::UnixDatagram)> { diff --git a/src/sys/unix/uds/listener.rs b/src/sys/unix/uds/listener.rs index 79bd14e..3e33b30 100644 --- a/src/sys/unix/uds/listener.rs +++ b/src/sys/unix/uds/listener.rs @@ -7,19 +7,15 @@ use std::path::Path; use std::{io, mem}; pub(crate) fn bind(path: &Path) -> io::Result<net::UnixListener> { - let socket = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?; let (sockaddr, socklen) = socket_addr(path)?; let sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr; - syscall!(bind(socket, sockaddr, socklen)) - .and_then(|_| syscall!(listen(socket, 1024))) - .map_err(|err| { - // Close the socket if we hit an error, ignoring the error from - // closing since we can't pass back two errors. - let _ = unsafe { libc::close(socket) }; - err - }) - .map(|_| unsafe { net::UnixListener::from_raw_fd(socket) }) + let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?; + let socket = unsafe { net::UnixListener::from_raw_fd(fd) }; + syscall!(bind(fd, sockaddr, socklen))?; + syscall!(listen(fd, 1024))?; + + Ok(socket) } pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> { @@ -45,10 +41,7 @@ pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, So target_os = "redox", // Android x86's seccomp profile forbids calls to `accept4(2)` // See https://github.com/tokio-rs/mio/issues/1445 for details - all( - target_arch = "x86", - target_os = "android" - ) + all(target_arch = "x86", target_os = "android"), )))] let socket = { let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC; @@ -62,10 +55,10 @@ pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, So }; #[cfg(any( - target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "redox", + target_os = "ios", + target_os = "macos", all(target_arch = "x86", target_os = "android") ))] let socket = syscall!(accept( diff --git a/src/sys/unix/uds/stream.rs b/src/sys/unix/uds/stream.rs index 9ae4867..461917c 100644 --- a/src/sys/unix/uds/stream.rs +++ b/src/sys/unix/uds/stream.rs @@ -7,23 +7,18 @@ use std::os::unix::net; use std::path::Path; pub(crate) fn connect(path: &Path) -> io::Result<net::UnixStream> { - let socket = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?; let (sockaddr, socklen) = socket_addr(path)?; let sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr; - match syscall!(connect(socket, sockaddr, socklen)) { + let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?; + let socket = unsafe { net::UnixStream::from_raw_fd(fd) }; + match syscall!(connect(fd, sockaddr, socklen)) { Ok(_) => {} Err(ref err) if err.raw_os_error() == Some(libc::EINPROGRESS) => {} - Err(e) => { - // Close the socket if we hit an error, ignoring the error - // from closing since we can't pass back two errors. - let _ = unsafe { libc::close(socket) }; - - return Err(e); - } + Err(e) => return Err(e), } - Ok(unsafe { net::UnixStream::from_raw_fd(socket) }) + Ok(socket) } pub(crate) fn pair() -> io::Result<(net::UnixStream, net::UnixStream)> { diff --git a/src/sys/unix/waker.rs b/src/sys/unix/waker.rs index de88e31..d8764c2 100644 --- a/src/sys/unix/waker.rs +++ b/src/sys/unix/waker.rs @@ -20,14 +20,11 @@ mod eventfd { impl Waker { pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> { - syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK)).and_then(|fd| { - // Turn the file descriptor into a file first so we're ensured - // it's closed when dropped, e.g. when register below fails. - let file = unsafe { File::from_raw_fd(fd) }; - selector - .register(fd, token, Interest::READABLE) - .map(|()| Waker { fd: file }) - }) + let fd = syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK))?; + let file = unsafe { File::from_raw_fd(fd) }; + + selector.register(fd, token, Interest::READABLE)?; + Ok(Waker { fd: file }) } pub fn wake(&self) -> io::Result<()> { @@ -82,11 +79,9 @@ mod kqueue { impl Waker { pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> { - selector.try_clone().and_then(|selector| { - selector - .setup_waker(token) - .map(|()| Waker { selector, token }) - }) + let selector = selector.try_clone()?; + selector.setup_waker(token)?; + Ok(Waker { selector, token }) } pub fn wake(&self) -> io::Result<()> { @@ -127,13 +122,11 @@ mod pipe { pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> { let mut fds = [-1; 2]; syscall!(pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK | libc::O_CLOEXEC))?; - // Turn the file descriptors into files first so we're ensured - // they're closed when dropped, e.g. when register below fails. let sender = unsafe { File::from_raw_fd(fds[1]) }; let receiver = unsafe { File::from_raw_fd(fds[0]) }; - selector - .register(fds[0], token, Interest::READABLE) - .map(|()| Waker { sender, receiver }) + + selector.register(fds[0], token, Interest::READABLE)?; + Ok(Waker { sender, receiver }) } pub fn wake(&self) -> io::Result<()> { diff --git a/src/sys/windows/iocp.rs b/src/sys/windows/iocp.rs index 142b6fc..262c8f2 100644 --- a/src/sys/windows/iocp.rs +++ b/src/sys/windows/iocp.rs @@ -224,17 +224,12 @@ impl CompletionStatus { #[inline] fn duration_millis(dur: Option<Duration>) -> u32 { if let Some(dur) = dur { - let dur_ms = dur.as_millis(); - // as_millis() truncates, so round nonzero <1ms timeouts up to 1ms. This avoids turning - // submillisecond timeouts into immediate reutrns unless the caller explictly requests that - // by specifiying a zero timeout. - let dur_ms = dur_ms - + if dur_ms == 0 && dur.subsec_nanos() != 0 { - 1 - } else { - 0 - }; - std::cmp::min(dur_ms, u32::MAX as u128) as u32 + // `Duration::as_millis` truncates, so round up. This avoids + // turning sub-millisecond timeouts into a zero timeout, unless + // the caller explicitly requests that by specifying a zero + // timeout. + let dur_ms = (dur + Duration::from_nanos(999_999)).as_millis(); + cmp::min(dur_ms, u32::MAX as u128) as u32 } else { u32::MAX } diff --git a/src/sys/windows/net.rs b/src/sys/windows/net.rs index 102ba79..44f459a 100644 --- a/src/sys/windows/net.rs +++ b/src/sys/windows/net.rs @@ -4,12 +4,13 @@ use std::net::SocketAddr; use std::sync::Once; use windows_sys::Win32::Networking::WinSock::{ - ioctlsocket, socket, AF_INET, AF_INET6, FIONBIO, IN6_ADDR, IN6_ADDR_0, INVALID_SOCKET, IN_ADDR, - IN_ADDR_0, SOCKADDR, SOCKADDR_IN, SOCKADDR_IN6, SOCKADDR_IN6_0, SOCKET, + closesocket, ioctlsocket, socket, AF_INET, AF_INET6, FIONBIO, IN6_ADDR, IN6_ADDR_0, + INVALID_SOCKET, IN_ADDR, IN_ADDR_0, SOCKADDR, SOCKADDR_IN, SOCKADDR_IN6, SOCKADDR_IN6_0, + SOCKET, }; /// Initialise the network stack for Windows. -pub(crate) fn init() { +fn init() { static INIT: Once = Once::new(); INIT.call_once(|| { // Let standard library call `WSAStartup` for us, we can't do it @@ -26,18 +27,24 @@ pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: u16) -> io::Result<SO SocketAddr::V6(..) => AF_INET6, }; - new_socket(domain, socket_type) + new_socket(domain.into(), socket_type) } pub(crate) fn new_socket(domain: u32, socket_type: u16) -> io::Result<SOCKET> { - syscall!( + init(); + + let socket = syscall!( socket(domain as i32, socket_type as i32, 0), PartialEq::eq, INVALID_SOCKET - ) - .and_then(|socket| { - syscall!(ioctlsocket(socket, FIONBIO, &mut 1), PartialEq::ne, 0).map(|_| socket as SOCKET) - }) + )?; + + if let Err(err) = syscall!(ioctlsocket(socket, FIONBIO, &mut 1), PartialEq::ne, 0) { + let _ = unsafe { closesocket(socket) }; + return Err(err); + } + + Ok(socket as SOCKET) } /// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level diff --git a/src/sys/windows/tcp.rs b/src/sys/windows/tcp.rs index 533074b..addd1e8 100644 --- a/src/sys/windows/tcp.rs +++ b/src/sys/windows/tcp.rs @@ -2,19 +2,12 @@ use std::io; use std::net::{self, SocketAddr}; use std::os::windows::io::AsRawSocket; -use windows_sys::Win32::Networking::WinSock::{ - self, AF_INET, AF_INET6, SOCKET, SOCKET_ERROR, SOCK_STREAM, -}; +use windows_sys::Win32::Networking::WinSock::{self, SOCKET, SOCKET_ERROR, SOCK_STREAM}; -use crate::sys::windows::net::{init, new_socket, socket_addr}; +use crate::sys::windows::net::{new_ip_socket, socket_addr}; pub(crate) fn new_for_addr(address: SocketAddr) -> io::Result<SOCKET> { - init(); - let domain = match address { - SocketAddr::V4(_) => AF_INET, - SocketAddr::V6(_) => AF_INET6, - }; - new_socket(domain, SOCK_STREAM) + new_ip_socket(address, SOCK_STREAM) } pub(crate) fn bind(socket: &net::TcpListener, addr: SocketAddr) -> io::Result<()> { diff --git a/src/sys/windows/udp.rs b/src/sys/windows/udp.rs index 91516cc..87e269f 100644 --- a/src/sys/windows/udp.rs +++ b/src/sys/windows/udp.rs @@ -4,28 +4,23 @@ use std::net::{self, SocketAddr}; use std::os::windows::io::{AsRawSocket, FromRawSocket}; use std::os::windows::raw::SOCKET as StdSocket; // windows-sys uses usize, stdlib uses u32/u64. -use crate::sys::windows::net::{init, new_ip_socket, socket_addr}; +use crate::sys::windows::net::{new_ip_socket, socket_addr}; use windows_sys::Win32::Networking::WinSock::{ - bind as win_bind, closesocket, getsockopt, IPPROTO_IPV6, IPV6_V6ONLY, SOCKET_ERROR, SOCK_DGRAM, + bind as win_bind, getsockopt, IPPROTO_IPV6, IPV6_V6ONLY, SOCKET_ERROR, SOCK_DGRAM, }; pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> { - init(); - new_ip_socket(addr, SOCK_DGRAM).and_then(|socket| { - let (raw_addr, raw_addr_length) = socket_addr(&addr); - syscall!( - win_bind(socket, raw_addr.as_ptr(), raw_addr_length,), - PartialEq::eq, - SOCKET_ERROR - ) - .map_err(|err| { - // Close the socket if we hit an error, ignoring the error - // from closing since we can't pass back two errors. - let _ = unsafe { closesocket(socket) }; - err - }) - .map(|_| unsafe { net::UdpSocket::from_raw_socket(socket as StdSocket) }) - }) + let raw_socket = new_ip_socket(addr, SOCK_DGRAM)?; + let socket = unsafe { net::UdpSocket::from_raw_socket(raw_socket as StdSocket) }; + + let (raw_addr, raw_addr_length) = socket_addr(&addr); + syscall!( + win_bind(raw_socket, raw_addr.as_ptr(), raw_addr_length), + PartialEq::eq, + SOCKET_ERROR + )?; + + Ok(socket) } pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> { |