Merge pull request #1036 from notgull/main

Implement I/O-safe traits on types
pull/1057/head
Josh Triplett 2 years ago committed by GitHub
commit 7c95bce535
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -109,6 +109,21 @@ jobs:
command: check
args: --all --features tokio02
check_io_safety_feature:
name: Check io_safety feature
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v3
- name: check io_safety
uses: actions-rs/cargo@v1
with:
command: check
args: --all --features io_safety
cross:
name: Cross compile
runs-on: ubuntu-latest

@ -58,6 +58,7 @@ alloc = [
tokio1 = ["async-global-executor/tokio"]
tokio02 = ["async-global-executor/tokio02"]
tokio03 = ["async-global-executor/tokio03"]
io_safety = []
[dependencies]
async-attributes = { version = "1.1.1", optional = true }

@ -15,6 +15,8 @@ use crate::prelude::*;
use crate::task::{spawn_blocking, Context, Poll, Waker};
use crate::utils::Context as _;
const ARC_TRY_UNWRAP_EXPECT: &str = "cannot acquire ownership of the file handle after drop";
/// An open file on the filesystem.
///
/// Depending on what options the file was opened with, this type can be used for reading and/or
@ -415,6 +417,15 @@ impl From<std::fs::File> for File {
cfg_unix! {
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
impl File {
fn into_std_file(self) -> std::fs::File {
let file = self.file.clone();
drop(self);
Arc::try_unwrap(file)
.expect(ARC_TRY_UNWRAP_EXPECT)
}
}
impl AsRawFd for File {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
@ -429,11 +440,29 @@ cfg_unix! {
impl IntoRawFd for File {
fn into_raw_fd(self) -> RawFd {
let file = self.file.clone();
drop(self);
Arc::try_unwrap(file)
.expect("cannot acquire ownership of the file handle after drop")
.into_raw_fd()
self.into_std_file().into_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
impl AsFd for File {
fn as_fd(&self) -> BorrowedFd<'_> {
self.file.as_fd()
}
}
impl From<OwnedFd> for File {
fn from(fd: OwnedFd) -> Self {
std::fs::File::from(fd).into()
}
}
impl From<File> for OwnedFd {
fn from(val: File) -> OwnedFd {
self.into_std_file().into()
}
}
}
}
@ -458,10 +487,36 @@ cfg_windows! {
let file = self.file.clone();
drop(self);
Arc::try_unwrap(file)
.expect("cannot acquire ownership of the file handle after drop")
.expect(ARC_TRY_UNWRAP_EXPECT)
.into_raw_handle()
}
}
cfg_io_safety! {
use crate::os::windows::io::{AsHandle, BorrowedHandle, OwnedHandle};
impl AsHandle for File {
fn as_handle(&self) -> BorrowedHandle<'_> {
self.file.as_handle()
}
}
impl From<OwnedHandle> for File {
fn from(handle: OwnedHandle) -> Self {
std::fs::File::from(handle).into()
}
}
impl From<File> for OwnedHandle {
fn from(val: File) -> OwnedHandle {
let file = val.file.clone();
drop(val);
Arc::try_unwrap(file)
.expect(ARC_TRY_UNWRAP_EXPECT)
.into()
}
}
}
}
/// An async mutex with non-borrowing lock guards.

@ -180,6 +180,16 @@ cfg_unix! {
std::io::stderr().as_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd};
impl AsFd for Stderr {
fn as_fd(&self) -> BorrowedFd<'_> {
std::io::stderr().as_fd()
}
}
}
}
cfg_windows! {
@ -190,4 +200,14 @@ cfg_windows! {
std::io::stderr().as_raw_handle()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsHandle, BorrowedHandle};
impl AsHandle for Stderr {
fn as_handle(&self) -> BorrowedHandle<'_> {
std::io::stderr().as_handle()
}
}
}
}

@ -206,6 +206,16 @@ cfg_unix! {
std::io::stdin().as_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd};
impl AsFd for Stderr {
fn as_fd(&self) -> BorrowedFd<'_> {
std::io::stdin().as_fd()
}
}
}
}
cfg_windows! {
@ -216,4 +226,14 @@ cfg_windows! {
std::io::stdin().as_raw_handle()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd};
impl AsFd for Stdin {
fn as_fd(&self) -> BorrowedFd<'_> {
std::io::stdin().as_fd()
}
}
}
}

@ -180,6 +180,16 @@ cfg_unix! {
std::io::stdout().as_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd};
impl AsFd for Stdout {
fn as_fd(&self) -> BorrowedFd<'_> {
std::io::stdout().as_fd()
}
}
}
}
cfg_windows! {
@ -190,4 +200,14 @@ cfg_windows! {
std::io::stdout().as_raw_handle()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsHandle, BorrowedHandle};
impl AsHandle for Stdout {
fn as_handle(&self) -> BorrowedHandle<'_> {
std::io::stdout().as_handle()
}
}
}
}

@ -282,6 +282,28 @@ cfg_unix! {
self.watcher.into_inner().unwrap().into_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
impl AsFd for TcpListener {
fn as_fd(&self) -> BorrowedFd<'_> {
self.watcher.get_ref().as_fd()
}
}
impl From<OwnedFd> for TcpListener {
fn from(fd: OwnedFd) -> TcpListener {
std::net::TcpListener::from(fd).into()
}
}
impl From<TcpListener> for OwnedFd {
fn from(listener: TcpListener) -> OwnedFd {
listener.watcher.into_inner().unwrap().into()
}
}
}
}
cfg_windows! {
@ -306,4 +328,26 @@ cfg_windows! {
self.watcher.into_inner().unwrap().into_raw_socket()
}
}
cfg_io_safety! {
use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket};
impl AsSocket for TcpListener {
fn as_socket(&self) -> BorrowedSocket<'_> {
self.watcher.get_ref().as_socket()
}
}
impl From<OwnedSocket> for TcpListener {
fn from(fd: OwnedSocket) -> TcpListener {
std::net::TcpListener::from(fd).into()
}
}
impl From<TcpListener> for OwnedSocket {
fn from(listener: TcpListener) -> OwnedSocket {
listener.watcher.into_inner().unwrap().into()
}
}
}
}

@ -416,6 +416,28 @@ cfg_unix! {
self.as_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
impl AsFd for TcpStream {
fn as_fd(&self) -> BorrowedFd<'_> {
self.watcher.get_ref().as_fd()
}
}
impl From<OwnedFd> for TcpStream {
fn from(fd: OwnedFd) -> TcpStream {
std::net::TcpStream::from(fd).into()
}
}
impl From<TcpStream> for OwnedFd {
fn from(stream: TcpStream) -> OwnedFd {
stream.watcher.into_inner().unwrap().into()
}
}
}
}
cfg_windows! {
@ -443,4 +465,26 @@ cfg_windows! {
self.as_raw_socket()
}
}
cfg_io_safety! {
use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket};
impl AsSocket for TcpStream {
fn as_socket(&self) -> BorrowedSocket<'_> {
self.watcher.get_ref().as_socket()
}
}
impl From<OwnedSocket> for TcpStream {
fn from(fd: OwnedSocket) -> TcpStream {
std::net::TcpListener::from(fd).into()
}
}
impl From<TcpStream> for OwnedSocket {
fn from(stream: TcpStream) -> OwnedSocket {
stream.watcher.into_inner().unwrap().into()
}
}
}
}

@ -562,6 +562,28 @@ cfg_unix! {
self.watcher.into_inner().unwrap().into_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
impl AsFd for UdpSocket {
fn as_fd(&self) -> BorrowedFd<'_> {
self.watcher.get_ref().as_fd()
}
}
impl From<OwnedFd> for UdpSocket {
fn from(fd: OwnedFd) -> UdpSocket {
std::net::TcpStream::from(fd).into()
}
}
impl From<UdpSocket> for OwnedFd {
fn from(stream: UdpSocket) -> OwnedFd {
stream.watcher.into_inner().unwrap().into()
}
}
}
}
cfg_windows! {
@ -586,4 +608,26 @@ cfg_windows! {
self.watcher.into_inner().unwrap().into_raw_socket()
}
}
cfg_io_safety! {
use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket};
impl AsSocket for UdpSocket {
fn as_socket(&self) -> BorrowedSocket<'_> {
self.watcher.get_ref().as_socket()
}
}
impl From<OwnedSocket> for UdpSocket {
fn from(fd: OwnedSocket) -> UdpSocket {
std::net::TcpListener::from(fd).into()
}
}
impl From<UdpSocket> for OwnedSocket {
fn from(stream: UdpSocket) -> OwnedSocket {
stream.watcher.into_inner().unwrap().into()
}
}
}
}

@ -2,6 +2,10 @@
cfg_not_docs! {
pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
cfg_io_safety! {
pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
}
}
cfg_docs! {
@ -51,4 +55,9 @@ cfg_docs! {
/// and must close the descriptor once it's no longer needed.
fn into_raw_fd(self) -> RawFd;
}
cfg_io_safety! {
#[doc(inline)]
pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
}
}

@ -340,3 +340,25 @@ impl IntoRawFd for UnixDatagram {
self.watcher.into_inner().unwrap().into_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
impl AsFd for UnixDatagram {
fn as_fd(&self) -> BorrowedFd<'_> {
self.watcher.get_ref().as_fd()
}
}
impl From<OwnedFd> for UnixDatagram {
fn from(fd: OwnedFd) -> UnixDatagram {
std::net::TcpStream::from(fd).into()
}
}
impl From<UnixDatagram> for OwnedFd {
fn from(stream: UnixDatagram) -> OwnedFd {
stream.watcher.into_inner().unwrap().into()
}
}
}

@ -233,3 +233,25 @@ impl IntoRawFd for UnixListener {
self.watcher.into_inner().unwrap().into_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
impl AsFd for UnixListener {
fn as_fd(&self) -> BorrowedFd<'_> {
self.watcher.get_ref().as_fd()
}
}
impl From<OwnedFd> for UnixListener {
fn from(fd: OwnedFd) -> UnixListener {
std::net::TcpStream::from(fd).into()
}
}
impl From<UnixListener> for OwnedFd {
fn from(stream: UnixListener) -> OwnedFd {
stream.watcher.into_inner().unwrap().into()
}
}
}

@ -264,3 +264,25 @@ impl IntoRawFd for UnixStream {
(*self.watcher).get_ref().try_clone().unwrap().into_raw_fd()
}
}
cfg_io_safety! {
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
impl AsFd for UnixStream {
fn as_fd(&self) -> BorrowedFd<'_> {
self.watcher.get_ref().as_fd()
}
}
impl From<OwnedFd> for UnixStream {
fn from(fd: OwnedFd) -> UnixStream {
std::net::TcpStream::from(fd).into()
}
}
impl From<UnixStream> for OwnedFd {
fn from(stream: UnixStream) -> OwnedFd {
stream.watcher.into_inner().unwrap().into()
}
}
}

@ -5,6 +5,13 @@ cfg_not_docs! {
AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle,
AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket,
};
cfg_io_safety! {
pub use std::os::windows::io::{
AsHandle, BorrowedHandle, OwnedHandle,
AsSocket, BorrowedSocket, OwnedSocket,
};
}
}
cfg_docs! {
@ -75,4 +82,12 @@ cfg_docs! {
/// it once it's no longer needed.
fn into_raw_socket(self) -> RawSocket;
}
cfg_io_safety! {
#[doc(inline)]
pub use std::os::windows::io::{
AsHandle, BorrowedHandle, OwnedHandle,
AsSocket, BorrowedSocket, OwnedSocket,
};
}
}

@ -239,3 +239,15 @@ macro_rules! cfg_default {
)*
}
}
/// Declares items that use I/O safety.
#[allow(unused_macros)]
#[doc(hidden)]
macro_rules! cfg_io_safety {
($($item:item)*) => {
$(
#[cfg(feature = "io-safety")]
$item
)*
}
}

Loading…
Cancel
Save