aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2023-02-16 15:24:49 +0100
committerJeff Vander Stoep <jeffv@google.com>2023-02-16 15:24:49 +0100
commit61fa94f41808c820ca6be95f722a0ef6efdc2a35 (patch)
tree051937287f30fd49716ced0af7befbb00ec9d957 /src
parent544dbb293255736fdafcca00c99e6f4b293c706a (diff)
downloadmio-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.rs38
-rw-r--r--src/net/tcp/stream.rs2
-rw-r--r--src/sys/unix/net.rs56
-rw-r--r--src/sys/unix/pipe.rs11
-rw-r--r--src/sys/unix/selector/epoll.rs21
-rw-r--r--src/sys/unix/selector/kqueue.rs53
-rw-r--r--src/sys/unix/selector/mod.rs8
-rw-r--r--src/sys/unix/tcp.rs13
-rw-r--r--src/sys/unix/udp.rs20
-rw-r--r--src/sys/unix/uds/datagram.rs12
-rw-r--r--src/sys/unix/uds/listener.rs25
-rw-r--r--src/sys/unix/uds/stream.rs15
-rw-r--r--src/sys/unix/waker.rs29
-rw-r--r--src/sys/windows/iocp.rs17
-rw-r--r--src/sys/windows/net.rs25
-rw-r--r--src/sys/windows/tcp.rs13
-rw-r--r--src/sys/windows/udp.rs31
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> {