diff --git a/Cargo.toml b/Cargo.toml index 1dfb5cf..1e50cbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ harness = false [dependencies] async-lock = "2.6" +cfg-if = "1" concurrent-queue = "2" futures-lite = "1.11.0" log = "0.4.11" diff --git a/src/lib.rs b/src/lib.rs index baebaa5..450c1b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -636,8 +636,23 @@ impl Async { // 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)?; + cfg_if::cfg_if! { + // ioctl(FIONBIO) sets the flag atomically, but we use this only on Linux + // for now, as with the standard library, because it seems to behave + // differently depending on the platform. + // https://github.com/rust-lang/rust/commit/efeb42be2837842d1beb47b51bb693c7474aba3d + // https://github.com/libuv/libuv/blob/e9d91fccfc3e5ff772d5da90e1c4a24061198ca0/src/unix/poll.c#L78-L80 + // https://github.com/tokio-rs/mio/commit/0db49f6d5caf54b12176821363d154384357e70a + if #[cfg(target_os = "linux")] { + rustix::io::ioctl_fionbio(fd, true)?; + } else { + let previous = rustix::fs::fcntl_getfl(fd)?; + let new = previous | rustix::fs::OFlags::NONBLOCK; + if new != previous { + rustix::fs::fcntl_setfl(fd, new)?; + } + } + } Ok(Async { source: Reactor::get().insert_io(raw)?,