diff --git a/tokio/build.rs b/tokio/build.rs index ddade2876bb..0e2480ed846 100644 --- a/tokio/build.rs +++ b/tokio/build.rs @@ -24,6 +24,19 @@ const CONST_MUTEX_NEW_PROBE: &str = r#" } "#; +const AS_FD_PROBE: &str = r#" +{ + #![allow(unused_imports)] + + #[cfg(unix)] + use std::os::unix::prelude::AsFd as _; + #[cfg(windows)] + use std::os::windows::prelude::AsSocket as _; + #[cfg(target = "wasm32-wasi")] + use std::os::wasi::prelude::AsFd as _; +} +"#; + const TARGET_HAS_ATOMIC_PROBE: &str = r#" { #[cfg(target_has_atomic = "ptr")] @@ -43,6 +56,7 @@ fn main() { let mut enable_addr_of = false; let mut enable_target_has_atomic = false; let mut enable_const_mutex_new = false; + let mut enable_as_fd = false; let mut target_needs_atomic_u64_fallback = false; match AutoCfg::new() { @@ -117,6 +131,21 @@ fn main() { enable_const_mutex_new = true; } } + + // The `AsFd` family of traits were made stable in 1.63. + if ac.probe_rustc_version(1, 64) { + enable_as_fd = true; + } else if ac.probe_rustc_version(1, 63) { + // This compiler claims to be 1.63, but there are some nightly + // compilers that claim to be 1.63 without supporting the + // feature. Explicitly probe to check if code using them + // compiles. + // + // The oldest nightly that supports the feature is 2022-06-16. + if ac.probe_expression(AS_FD_PROBE) { + enable_as_fd = true; + } + } } Err(e) => { @@ -162,6 +191,14 @@ fn main() { autocfg::emit("tokio_no_const_mutex_new") } + if !enable_as_fd { + // To disable this feature on compilers that support it, you can + // explicitly pass this flag with the following environment variable: + // + // RUSTFLAGS="--cfg tokio_no_as_fd" + autocfg::emit("tokio_no_as_fd"); + } + if target_needs_atomic_u64_fallback { // To disable this feature on compilers that support it, you can // explicitly pass this flag with the following environment variable: diff --git a/tokio/src/fs/file.rs b/tokio/src/fs/file.rs index d513beb05a4..bd8c9c27165 100644 --- a/tokio/src/fs/file.rs +++ b/tokio/src/fs/file.rs @@ -725,6 +725,15 @@ impl std::os::unix::io::AsRawFd for File { } } +#[cfg(all(unix, not(tokio_no_as_fd)))] +impl std::os::unix::io::AsFd for File { + fn as_fd(&self) -> std::os::unix::io::BorrowedFd<'_> { + unsafe { + std::os::unix::io::BorrowedFd::borrow_raw(std::os::unix::io::AsRawFd::as_raw_fd(self)) + } + } +} + #[cfg(unix)] impl std::os::unix::io::FromRawFd for File { unsafe fn from_raw_fd(fd: std::os::unix::io::RawFd) -> Self { @@ -739,6 +748,17 @@ impl std::os::windows::io::AsRawHandle for File { } } +#[cfg(all(windows, not(tokio_no_as_fd)))] +impl std::os::windows::io::AsHandle for File { + fn as_handle(&self) -> std::os::windows::io::BorrowedHandle<'_> { + unsafe { + std::os::windows::io::BorrowedHandle::borrow_raw( + std::os::windows::io::AsRawHandle::as_raw_handle(self), + ) + } + } +} + #[cfg(windows)] impl std::os::windows::io::FromRawHandle for File { unsafe fn from_raw_handle(handle: std::os::windows::io::RawHandle) -> Self { diff --git a/tokio/src/net/tcp/listener.rs b/tokio/src/net/tcp/listener.rs index 4441313703e..825e960e6d9 100644 --- a/tokio/src/net/tcp/listener.rs +++ b/tokio/src/net/tcp/listener.rs @@ -407,6 +407,13 @@ mod sys { self.io.as_raw_fd() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsFd for TcpListener { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } } cfg_unstable! { @@ -420,6 +427,13 @@ cfg_unstable! { self.io.as_raw_fd() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsFd for TcpListener { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } } } @@ -433,4 +447,11 @@ mod sys { self.io.as_raw_socket() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsSocket for TcpListener { + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } + } + } } diff --git a/tokio/src/net/tcp/socket.rs b/tokio/src/net/tcp/socket.rs index 09349fe53eb..9c76e040857 100644 --- a/tokio/src/net/tcp/socket.rs +++ b/tokio/src/net/tcp/socket.rs @@ -4,10 +4,14 @@ use std::fmt; use std::io; use std::net::SocketAddr; +#[cfg(all(unix, not(tokio_no_as_fd)))] +use std::os::unix::io::{AsFd, BorrowedFd}; #[cfg(unix)] use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; #[cfg(windows)] use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; +#[cfg(all(windows, not(tokio_no_as_fd)))] +use std::os::windows::io::{AsSocket, BorrowedSocket}; use std::time::Duration; cfg_net! { @@ -737,6 +741,13 @@ impl AsRawFd for TcpSocket { } } +#[cfg(all(unix, not(tokio_no_as_fd)))] +impl AsFd for TcpSocket { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + #[cfg(unix)] impl FromRawFd for TcpSocket { /// Converts a `RawFd` to a `TcpSocket`. @@ -772,6 +783,13 @@ impl AsRawSocket for TcpSocket { } } +#[cfg(all(windows, not(tokio_no_as_fd)))] +impl AsSocket for TcpSocket { + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } + } +} + #[cfg(windows)] impl FromRawSocket for TcpSocket { /// Converts a `RawSocket` to a `TcpStream`. diff --git a/tokio/src/net/tcp/stream.rs b/tokio/src/net/tcp/stream.rs index b17d33feaea..ae5fd72d542 100644 --- a/tokio/src/net/tcp/stream.rs +++ b/tokio/src/net/tcp/stream.rs @@ -1342,6 +1342,13 @@ mod sys { self.io.as_raw_fd() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsFd for TcpStream { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } } #[cfg(windows)] @@ -1354,6 +1361,13 @@ mod sys { self.io.as_raw_socket() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsSocket for TcpStream { + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } + } + } } #[cfg(all(tokio_unstable, tokio_wasi))] @@ -1366,4 +1380,11 @@ mod sys { self.io.as_raw_fd() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsFd for TcpStream { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } } diff --git a/tokio/src/net/udp.rs b/tokio/src/net/udp.rs index 213d9149dad..b3d23e3d5a6 100644 --- a/tokio/src/net/udp.rs +++ b/tokio/src/net/udp.rs @@ -1691,7 +1691,7 @@ impl fmt::Debug for UdpSocket { } } -#[cfg(all(unix))] +#[cfg(unix)] mod sys { use super::UdpSocket; use std::os::unix::prelude::*; @@ -1701,6 +1701,13 @@ mod sys { self.io.as_raw_fd() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsFd for UdpSocket { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } } #[cfg(windows)] @@ -1713,4 +1720,11 @@ mod sys { self.io.as_raw_socket() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsSocket for UdpSocket { + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } + } + } } diff --git a/tokio/src/net/unix/datagram/socket.rs b/tokio/src/net/unix/datagram/socket.rs index 76c6b191283..371a10f9ccd 100644 --- a/tokio/src/net/unix/datagram/socket.rs +++ b/tokio/src/net/unix/datagram/socket.rs @@ -5,6 +5,8 @@ use std::convert::TryFrom; use std::fmt; use std::io; use std::net::Shutdown; +#[cfg(not(tokio_no_as_fd))] +use std::os::unix::io::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::os::unix::net; use std::path::Path; @@ -1436,3 +1438,10 @@ impl AsRawFd for UnixDatagram { self.io.as_raw_fd() } } + +#[cfg(not(tokio_no_as_fd))] +impl AsFd for UnixDatagram { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} diff --git a/tokio/src/net/unix/listener.rs b/tokio/src/net/unix/listener.rs index 9887f7343be..1a2614feff4 100644 --- a/tokio/src/net/unix/listener.rs +++ b/tokio/src/net/unix/listener.rs @@ -4,6 +4,8 @@ use crate::net::unix::{SocketAddr, UnixStream}; use std::convert::TryFrom; use std::fmt; use std::io; +#[cfg(not(tokio_no_as_fd))] +use std::os::unix::io::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::os::unix::net; use std::path::Path; @@ -208,3 +210,10 @@ impl AsRawFd for UnixListener { self.io.as_raw_fd() } } + +#[cfg(not(tokio_no_as_fd))] +impl AsFd for UnixListener { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} diff --git a/tokio/src/net/unix/pipe.rs b/tokio/src/net/unix/pipe.rs index 0775717b0c6..188ac68b11c 100644 --- a/tokio/src/net/unix/pipe.rs +++ b/tokio/src/net/unix/pipe.rs @@ -7,6 +7,8 @@ use mio::unix::pipe as mio_pipe; use std::fs::File; use std::io::{self, Read, Write}; use std::os::unix::fs::{FileTypeExt, OpenOptionsExt}; +#[cfg(not(tokio_no_as_fd))] +use std::os::unix::io::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::path::Path; use std::pin::Pin; @@ -662,6 +664,13 @@ impl AsRawFd for Sender { } } +#[cfg(not(tokio_no_as_fd))] +impl AsFd for Sender { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + /// Reading end of a Unix pipe. /// /// It can be constructed from a FIFO file with [`OpenOptions::open_receiver`]. @@ -1161,6 +1170,13 @@ impl AsRawFd for Receiver { } } +#[cfg(not(tokio_no_as_fd))] +impl AsFd for Receiver { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + /// Checks if file is a FIFO fn is_fifo(file: &File) -> io::Result { Ok(file.metadata()?.file_type().is_fifo()) diff --git a/tokio/src/net/unix/stream.rs b/tokio/src/net/unix/stream.rs index c249bf4b269..80df2496532 100644 --- a/tokio/src/net/unix/stream.rs +++ b/tokio/src/net/unix/stream.rs @@ -9,6 +9,8 @@ use std::convert::TryFrom; use std::fmt; use std::io::{self, Read, Write}; use std::net::Shutdown; +#[cfg(not(tokio_no_as_fd))] +use std::os::unix::io::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::os::unix::net; use std::path::Path; @@ -1000,3 +1002,10 @@ impl AsRawFd for UnixStream { self.io.as_raw_fd() } } + +#[cfg(not(tokio_no_as_fd))] +impl AsFd for UnixStream { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} diff --git a/tokio/src/process/mod.rs b/tokio/src/process/mod.rs index feada06f6d3..0aa72c6f2a3 100644 --- a/tokio/src/process/mod.rs +++ b/tokio/src/process/mod.rs @@ -1428,6 +1428,8 @@ impl TryInto for ChildStderr { #[cfg(unix)] mod sys { + #[cfg(not(tokio_no_as_fd))] + use std::os::unix::io::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, RawFd}; use super::{ChildStderr, ChildStdin, ChildStdout}; @@ -1438,21 +1440,44 @@ mod sys { } } + #[cfg(not(tokio_no_as_fd))] + impl AsFd for ChildStdin { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } + impl AsRawFd for ChildStdout { fn as_raw_fd(&self) -> RawFd { self.inner.as_raw_fd() } } + #[cfg(not(tokio_no_as_fd))] + impl AsFd for ChildStdout { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } + impl AsRawFd for ChildStderr { fn as_raw_fd(&self) -> RawFd { self.inner.as_raw_fd() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsFd for ChildStderr { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } } #[cfg(windows)] mod sys { + #[cfg(not(tokio_no_as_fd))] + use std::os::windows::io::{AsHandle, BorrowedHandle}; use std::os::windows::io::{AsRawHandle, RawHandle}; use super::{ChildStderr, ChildStdin, ChildStdout}; @@ -1463,17 +1488,38 @@ mod sys { } } + #[cfg(not(tokio_no_as_fd))] + impl AsHandle for ChildStdin { + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } + } + } + impl AsRawHandle for ChildStdout { fn as_raw_handle(&self) -> RawHandle { self.inner.as_raw_handle() } } + #[cfg(not(tokio_no_as_fd))] + impl AsHandle for ChildStdout { + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } + } + } + impl AsRawHandle for ChildStderr { fn as_raw_handle(&self) -> RawHandle { self.inner.as_raw_handle() } } + + #[cfg(not(tokio_no_as_fd))] + impl AsHandle for ChildStderr { + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } + } + } } #[cfg(all(test, not(loom)))] diff --git a/tokio/src/process/unix/mod.rs b/tokio/src/process/unix/mod.rs index 78c792cc765..41857f49c8f 100644 --- a/tokio/src/process/unix/mod.rs +++ b/tokio/src/process/unix/mod.rs @@ -39,6 +39,8 @@ use std::fmt; use std::fs::File; use std::future::Future; use std::io; +#[cfg(not(tokio_no_as_fd))] +use std::os::unix::io::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::pin::Pin; use std::process::{Child as StdChild, ExitStatus, Stdio}; @@ -194,6 +196,13 @@ impl AsRawFd for Pipe { } } +#[cfg(not(tokio_no_as_fd))] +impl AsFd for Pipe { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + pub(crate) fn convert_to_stdio(io: ChildStdio) -> io::Result { let mut fd = io.inner.into_inner()?.fd; @@ -246,6 +255,13 @@ impl AsRawFd for ChildStdio { } } +#[cfg(not(tokio_no_as_fd))] +impl AsFd for ChildStdio { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + impl AsyncWrite for ChildStdio { fn poll_write( self: Pin<&mut Self>,