io: add implementations of AsFd/AsHandle/AsSocket (#5514)

This commit is contained in:
Steven Fackler
2023-03-11 17:04:01 +01:00
committed by GitHub
parent 8eb94a33c0
commit e34978233b
12 changed files with 237 additions and 1 deletions
+37
View File
@@ -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:
+20
View File
@@ -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 {
+21
View File
@@ -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()) }
}
}
}
+18
View File
@@ -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`.
+21
View File
@@ -1378,6 +1378,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)]
@@ -1390,6 +1397,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))]
@@ -1402,4 +1416,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()) }
}
}
}
+15 -1
View File
@@ -1727,7 +1727,7 @@ impl fmt::Debug for UdpSocket {
}
}
#[cfg(all(unix))]
#[cfg(unix)]
mod sys {
use super::UdpSocket;
use std::os::unix::prelude::*;
@@ -1737,6 +1737,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)]
@@ -1749,4 +1756,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()) }
}
}
}
+9
View File
@@ -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;
@@ -1472,3 +1474,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()) }
}
}
+9
View File
@@ -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()) }
}
}
+16
View File
@@ -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<bool> {
Ok(file.metadata()?.file_type().is_fifo())
+9
View File
@@ -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;
@@ -1036,3 +1038,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()) }
}
}
+46
View File
@@ -1428,6 +1428,8 @@ impl TryInto<Stdio> 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)))]
+16
View File
@@ -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<Stdio> {
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>,