From ee7a2999809c9a4a738f6e524fa53fd834e738b1 Mon Sep 17 00:00:00 2001 From: Thomas Barrett Date: Sun, 5 Feb 2023 22:51:48 -0800 Subject: [PATCH] Implement IntoRawFd for SharedFd and File --- src/fs/file.rs | 11 +++++++++++ src/io/shared_fd.rs | 25 ++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/fs/file.rs b/src/fs/file.rs index c25ce30b..99165880 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -855,6 +855,17 @@ impl File { } } +impl IntoRawFd for File { + // Consumes this object, returning the raw underlying file descriptor. + // Since all in-flight operations hold a reference to &self, the type-checker + // will ensure that there are no in-flight operations when this method is + // called. + fn into_raw_fd(self) -> RawFd { + // This should never panic. + self.fd.into_raw_fd() + } +} + impl FromRawFd for File { unsafe fn from_raw_fd(fd: RawFd) -> Self { File::from_shared_fd(SharedFd::new(fd)) diff --git a/src/io/shared_fd.rs b/src/io/shared_fd.rs index d573265f..867672b9 100644 --- a/src/io/shared_fd.rs +++ b/src/io/shared_fd.rs @@ -2,7 +2,7 @@ use crate::io::Close; use std::future::poll_fn; use std::cell::RefCell; -use std::os::unix::io::{FromRawFd, RawFd}; +use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; use std::rc::Rc; use std::task::Waker; @@ -39,6 +39,26 @@ enum State { /// The FD is fully closed Closed, + + // The FD is leaked. A SharedFd in this state will not be closed on drop. + // A SharedFd will only enter this state as a result of the `into_raw_fd` + // method. + Leaked, +} + +impl IntoRawFd for SharedFd { + // Consumes this object, returning the raw underlying file descriptor. + // This method will panic if there are any in-flight operations. + fn into_raw_fd(mut self) -> RawFd { + // Change the SharedFd state to `Leaked` so that the file-descriptor is + // not closed on drop. + if let Some(inner) = Rc::get_mut(&mut self.inner) { + let state = RefCell::get_mut(&mut inner.state); + *state = State::Leaked; + return self.raw_fd(); + } + panic!("unexpected operation in-flight") + } } impl SharedFd { @@ -139,6 +159,9 @@ impl Inner { Poll::Ready(()) } State::Closed => Poll::Ready(()), + // By definition, a SharedFd in a Leaked state is not closed, so we should + // never encounter this case while waiting for a SharedFd to close. + State::Leaked => unreachable!(), } }) .await;