diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9977332..96c536d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: matrix: # When updating this, the reminder to update the minimum supported # Rust version in Cargo.toml. - rust: ['1.46'] + rust: ['1.48'] steps: - uses: actions/checkout@v3 - name: Install Rust diff --git a/Cargo.toml b/Cargo.toml index e747ebd..1dfb5cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ name = "async-io" version = "1.12.0" authors = ["Stjepan Glavina "] edition = "2018" -rust-version = "1.46" +rust-version = "1.48" description = "Async I/O and timers" license = "Apache-2.0 OR MIT" repository = "https://github.com/smol-rs/async-io" @@ -25,6 +25,7 @@ futures-lite = "1.11.0" log = "0.4.11" parking = "2.0.0" polling = "2.0.0" +rustix = { version = "0.36.0", default-features = false, features = ["std", "fs"] } slab = "0.4.2" socket2 = { version = "0.4.2", features = ["all"] } waker-fn = "1.1.0" @@ -32,12 +33,6 @@ waker-fn = "1.1.0" [build-dependencies] autocfg = "1" -[target."cfg(unix)".dependencies] -libc = "0.2.77" - -[target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.42", features = ["Win32_Networking_WinSock"] } - [dev-dependencies] async-channel = "1" async-net = "1" @@ -49,7 +44,6 @@ tempfile = "3" [target.'cfg(target_os = "linux")'.dev-dependencies] inotify = { version = "0.10", default-features = false } -nix = { version = "0.25", default-features = false } timerfd = "1" [target.'cfg(windows)'.dev-dependencies] diff --git a/examples/linux-timerfd.rs b/examples/linux-timerfd.rs index e57053b..05ca38c 100644 --- a/examples/linux-timerfd.rs +++ b/examples/linux-timerfd.rs @@ -14,6 +14,7 @@ fn main() -> std::io::Result<()> { use async_io::Async; use futures_lite::future; + use rustix::fd::BorrowedFd; use timerfd::{SetTimeFlags, TimerFd, TimerState}; /// Sleeps using an OS timer. @@ -24,7 +25,14 @@ fn main() -> std::io::Result<()> { // When the OS timer fires, a 64-bit integer can be read from it. Async::new(timer)? - .read_with(|t| nix::unistd::read(t.as_raw_fd(), &mut [0u8; 8]).map_err(io::Error::from)) + .read_with(|t| { + // Safety: We assume `as_raw_fd()` returns a valid fd. When we + // can depend on Rust >= 1.63, where `AsFd` is stabilized, and + // when `TimerFd` implements it, we can remove this unsafe and + // simplify this. + let fd = unsafe { BorrowedFd::borrow_raw(t.as_raw_fd()) }; + rustix::io::read(fd, &mut [0u8; 8]).map_err(io::Error::from) + }) .await?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 0579e19..db6756b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -598,21 +598,19 @@ impl Async { /// # std::io::Result::Ok(()) }); /// ``` pub fn new(io: T) -> io::Result> { - let fd = io.as_raw_fd(); + let raw = io.as_raw_fd(); // Put the file descriptor in non-blocking mode. - unsafe { - let mut res = libc::fcntl(fd, libc::F_GETFL); - if res != -1 { - res = libc::fcntl(fd, libc::F_SETFL, res | libc::O_NONBLOCK); - } - if res == -1 { - return Err(io::Error::last_os_error()); - } - } + // + // Safety: We assume `as_raw_fd()` returns a valid fd. When we can + // depend on Rust >= 1.63, where `AsFd` is stabilized, and when + // `TimerFd` implements it, we can remove this unsafe and simplify this. + let fd = unsafe { rustix::fd::BorrowedFd::borrow_raw(raw) }; + let flags = rustix::fs::fcntl_getfl(fd)?; + rustix::fs::fcntl_setfl(fd, flags | rustix::fs::OFlags::NONBLOCK)?; Ok(Async { - source: Reactor::get().insert_io(fd)?, + source: Reactor::get().insert_io(raw)?, io: Some(io), }) } @@ -678,16 +676,14 @@ impl Async { /// ``` pub fn new(io: T) -> io::Result> { let sock = io.as_raw_socket(); + let borrowed = unsafe { rustix::fd::BorrowedFd::borrow_raw(sock) }; // Put the socket in non-blocking mode. - - use windows_sys::Win32::Networking::WinSock; - - let mut nonblocking = true as _; - let res = unsafe { WinSock::ioctlsocket(sock as _, WinSock::FIONBIO, &mut nonblocking) }; - if res != 0 { - return Err(io::Error::last_os_error()); - } + // + // Safety: We assume `as_raw_socket()` returns a valid fd. When we can + // depend on Rust >= 1.63, where `AsFd` is stabilized, and when + // `TimerFd` implements it, we can remove this unsafe and simplify this. + rustix::io::ioctl_fionbio(borrowed, true)?; Ok(Async { source: Reactor::get().insert_io(sock)?, @@ -1895,7 +1891,7 @@ fn connect(addr: SockAddr, domain: Domain, protocol: Option) -> io::Re match socket.connect(&addr) { Ok(_) => {} #[cfg(unix)] - Err(err) if err.raw_os_error() == Some(libc::EINPROGRESS) => {} + Err(err) if err.raw_os_error() == Some(rustix::io::Errno::INPROGRESS.raw_os_error()) => {} Err(err) if err.kind() == io::ErrorKind::WouldBlock => {} Err(err) => return Err(err), }