Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/driver/close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl Op<Close> {
pub(crate) fn close(fd: RawFd) -> io::Result<Op<Close>> {
use io_uring::{opcode, types};

Op::try_submit_with(Close { fd }, |close| {
Op::submit_with(Close { fd }, |close| {
opcode::Close::new(types::Fd(close.fd)).build()
})
}
Expand Down
12 changes: 0 additions & 12 deletions src/driver/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,6 @@ where
})
})
}

/// Try submitting an operation to uring
pub(super) fn try_submit_with<F>(data: T, f: F) -> io::Result<Self>
where
F: FnOnce(&mut T) -> squeue::Entry,
{
if CONTEXT.with(|cx| cx.is_set()) {
Op::submit_with(data, f)
} else {
Err(io::ErrorKind::Other.into())
}
}
}

impl<T> Future for Op<T, SingleCQE>
Expand Down
40 changes: 26 additions & 14 deletions src/driver/shared_fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ use std::os::unix::io::{FromRawFd, RawFd};
use std::rc::Rc;
use std::task::Waker;

use crate::runtime::CONTEXT;

// Tracks in-flight operations on a file descriptor. Ensures all in-flight
// operations complete before submitting the close.
//
// If the runtime is unavailable, will fall back to synchronous Close to ensure
// File resources are not leaked.
#[derive(Clone)]
pub(crate) struct SharedFd {
inner: Rc<Inner>,
Expand Down Expand Up @@ -74,21 +79,28 @@ impl Inner {
let state = RefCell::get_mut(&mut self.state);

// Submit a close operation
*state = match Op::close(self.fd) {
Ok(op) => State::Closing(op),
Err(_) => {
// Submitting the operation failed, we fall back on a
// synchronous `close`. This is safe as, at this point, we
// guarantee all in-flight operations have completed. The most
// common cause for an error is attempting to close the FD while
// off runtime.
//
// This is done by initializing a `File` with the FD and
// dropping it.
//
// TODO: Should we warn?
// If either:
// - runtime has already closed, or
// - submitting the Close operation fails
// we fall back on a synchronous `close`. This is safe as, at this point,
// we guarantee all in-flight operations have completed. The most
// common cause for an error is attempting to close the FD while
// off runtime.
//
// This is done by initializing a `File` with the FD and
// dropping it.
//
// TODO: Should we warn?
*state = match CONTEXT.try_with(|cx| cx.is_set()) {
Ok(true) => match Op::close(self.fd) {
Ok(op) => State::Closing(op),
Err(_) => {
let _ = unsafe { std::fs::File::from_raw_fd(self.fd) };
State::Closed
}
},
_ => {
let _ = unsafe { std::fs::File::from_raw_fd(self.fd) };

State::Closed
}
};
Expand Down