Skip to content

Commit

Permalink
io: add implementations of AsFd/AsHandle/AsSocket (#5514)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Mar 11, 2023
1 parent 8eb94a3 commit e349782
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 1 deletion.
37 changes: 37 additions & 0 deletions tokio/build.rs
Expand Up @@ -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")]
Expand All @@ -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() {
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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:
Expand Down
20 changes: 20 additions & 0 deletions tokio/src/fs/file.rs
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
21 changes: 21 additions & 0 deletions tokio/src/net/tcp/listener.rs
Expand Up @@ -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! {
Expand All @@ -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()) }
}
}
}
}

Expand All @@ -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 changes: 18 additions & 0 deletions tokio/src/net/tcp/socket.rs
Expand Up @@ -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! {
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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`.
Expand Down
21 changes: 21 additions & 0 deletions tokio/src/net/tcp/stream.rs
Expand Up @@ -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)]
Expand All @@ -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))]
Expand All @@ -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()) }
}
}
}
16 changes: 15 additions & 1 deletion tokio/src/net/udp.rs
Expand Up @@ -1727,7 +1727,7 @@ impl fmt::Debug for UdpSocket {
}
}

#[cfg(all(unix))]
#[cfg(unix)]
mod sys {
use super::UdpSocket;
use std::os::unix::prelude::*;
Expand All @@ -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)]
Expand All @@ -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 changes: 9 additions & 0 deletions tokio/src/net/unix/datagram/socket.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 changes: 9 additions & 0 deletions tokio/src/net/unix/listener.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 changes: 16 additions & 0 deletions tokio/src/net/unix/pipe.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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`].
Expand Down Expand Up @@ -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())
Expand Down
9 changes: 9 additions & 0 deletions tokio/src/net/unix/stream.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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()) }
}
}

0 comments on commit e349782

Please sign in to comment.