Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add implementations of AsFd/AsHandle/AsSocket #5514

Merged
merged 4 commits into from Mar 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -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)]
Expand All @@ -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))]
Expand All @@ -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()) }
}
}
}
16 changes: 15 additions & 1 deletion tokio/src/net/udp.rs
Expand Up @@ -1691,7 +1691,7 @@ impl fmt::Debug for UdpSocket {
}
}

#[cfg(all(unix))]
#[cfg(unix)]
mod sys {
use super::UdpSocket;
use std::os::unix::prelude::*;
Expand All @@ -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)]
Expand All @@ -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()) }
}
}
}
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 @@ -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()) }
}
}
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 @@ -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()) }
}
}