From c4786f40f2430dc1756b34ad0d9ccdc54d437d3a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 26 Jan 2022 13:53:05 -0800 Subject: [PATCH] Use rustix instead of direct calls to libc. Use the [rustix] syscall wrapper crate to factor out error handling and unsafe system calls. This reduces the amount of unsafe code here, and is a step towards factoring it out entirely once [`AsFd`] is stabilized and can replace `AsRawFd` for these kinds of uses. This does require incrementing the minimum required Rust version to 1.48. Please feel free to decline this PR if you don't wish to take on these new requirements. [rustix]: https://crates.io/crates/rustix/ [`AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html --- .clippy.toml | 2 +- .github/workflows/ci.yml | 2 +- Cargo.toml | 5 ++--- examples/linux-timerfd.rs | 8 +++++++- src/lib.rs | 22 ++++++++++------------ 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index eb66960..f691ea3 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1 @@ -msrv = "1.46" +msrv = "1.48" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a56acb3..377bf88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,7 +89,7 @@ jobs: matrix: # When updating this, the reminder to update the minimum supported # Rust version in Cargo.toml and .clippy.toml. - rust: ['1.46'] + rust: ['1.48'] steps: - uses: actions/checkout@v3 - name: Install Rust diff --git a/Cargo.toml b/Cargo.toml index 0496986..2fdde6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ name = "async-io" version = "1.7.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" @@ -26,7 +26,7 @@ socket2 = { version = "0.4.2", features = ["all"] } waker-fn = "1.1.0" [target."cfg(unix)".dependencies] -libc = "0.2.77" +rustix = { version = "0.35.6-beta.2", features = ["fs"] } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.9", features = ["winsock2"] } @@ -40,7 +40,6 @@ tempfile = "3" [target.'cfg(target_os = "linux")'.dev-dependencies] inotify = { version = "0.10", default-features = false } -nix = { version = "0.24", default-features = false } timerfd = "1" [target.'cfg(windows)'.dev-dependencies] diff --git a/examples/linux-timerfd.rs b/examples/linux-timerfd.rs index e57053b..b3478cd 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,12 @@ 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: Assume `as_raw_fd()` returns a valid fd; when `AsFd` + // is stabilized, we can remove this unsafe and simplify. + 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 29c3f5e..983924a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -525,21 +525,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 + // `AsFd` is stabilized and `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), }) } @@ -1779,7 +1777,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), }