Skip to content

Commit

Permalink
Implement IntoRawFd for SharedFd and File
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Barrett authored and Thomas Barrett committed Feb 6, 2023
1 parent afab7f2 commit ee7a299
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
25 changes: 24 additions & 1 deletion src/io/shared_fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit ee7a299

Please sign in to comment.