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 3 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
11 changes: 11 additions & 0 deletions tokio/build.rs
Expand Up @@ -43,6 +43,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 @@ -106,6 +107,7 @@ fn main() {
// The `Mutex::new` method was made const in 1.63.
if ac.probe_rustc_version(1, 64) {
enable_const_mutex_new = true;
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
Expand All @@ -115,6 +117,7 @@ fn main() {
// The oldest nightly that supports the feature is 2022-06-20.
if ac.probe_expression(CONST_MUTEX_NEW_PROBE) {
enable_const_mutex_new = true;
enable_as_fd = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would only be correct if AsFd was introduced in the exact same nightly as const mutex new. Can you have it use a separate probe here?

Generally, the purpose behind these checks is that some nightlies claim to be 1.63 without supporting the feature, and we need to make sure we actually compile on those nightlies too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like it'd be safer to just constrain the impls to 1.64 or greater to avoid having to deal with the nightly probe. Does that seem workable to you? Since there are different traits on different targets, the probe block is a bit more awkward here than for something like const Mutex::new.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just do this:

const UNIX_AS_FD_PROBE: &str = r#"
{
    #[allow(unused_imports)]
    use std::os::unix::io::AsFd as _;
}
"#;

const WINDOWS_AS_HANDLE_PROBE: &str = r#"
{
    #[allow(unused_imports)]
    use std::os::windows::io::AsHandle as _;
}
"#;

if ac.probe_expression(UNIX_AS_FD_PROBE) || ac.probe_expression(WINDOWS_AS_HANDLE_PROBE) {
    enable_as_fd = true;
}

The first nightly where the traits are considered stable is 2022-06-16 on both platforms, so it doesn't matter if the build script mixes up the platform during cross compilation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

}
}
Expand Down Expand Up @@ -162,6 +165,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()) }
}
}