This commit is contained in:
Nikolay Kim 2025-03-27 10:12:14 +01:00
parent ea74503736
commit a8db7de953
9 changed files with 84 additions and 45 deletions

View file

@ -49,7 +49,7 @@ async fn connect_inner(
let (sender, rx) = channel();
crate::rt_impl::connect::ConnectOps::current().connect(fd, addr, sender)?;
crate::rt_impl::connect::ConnectOps::current().connect("-", fd, addr, sender)?;
rx.await
.map_err(|_| io::Error::new(io::ErrorKind::Other, "IO Driver is gone"))

View file

@ -22,6 +22,7 @@ struct ConnectOpsBatcher {
struct Item {
fd: RawFd,
tag: &'static str,
sender: Sender<io::Result<()>>,
}
@ -49,6 +50,7 @@ impl ConnectOps {
pub(crate) fn connect(
&self,
tag: &'static str,
fd: RawFd,
addr: SockAddr,
sender: Sender<io::Result<()>>,
@ -59,10 +61,12 @@ impl ConnectOps {
res?;
}
let item = Item { fd, sender };
let item = Item { tag, fd, sender };
let id = self.0.connects.borrow_mut().insert(item);
self.0.api.attach(fd, id as u32, Some(Event::writable(0)));
self.0
.api
.attach(tag, fd, id as u32, Some(Event::writable(0)));
Ok(id)
}
}
@ -93,7 +97,7 @@ impl Handler for ConnectOpsBatcher {
Err(io::Error::from_raw_os_error(err))
};
self.inner.api.detach(item.fd, id as u32);
self.inner.api.detach(item.tag, item.fd, id as u32);
let _ = item.sender.send(res);
}
}
@ -105,7 +109,7 @@ impl Handler for ConnectOpsBatcher {
if connects.contains(id) {
let item = connects.remove(id);
let _ = item.sender.send(Err(err));
self.inner.api.detach(item.fd, id as u32);
self.inner.api.detach(item.tag, item.fd, id as u32);
}
}
}

View file

@ -16,8 +16,9 @@ pub(crate) struct StreamCtl<T> {
bitflags::bitflags! {
#[derive(Copy, Clone, Debug)]
struct Flags: u8 {
const RD = 0b0000_0001;
const WR = 0b0000_0010;
const RD = 0b0000_0001;
const WR = 0b0000_0010;
const CLOSED = 0b0000_0100;
}
}
@ -69,6 +70,7 @@ impl<T: AsRawFd + 'static> StreamOps<T> {
pub(crate) fn register(&self, io: T, context: IoContext) -> StreamCtl<T> {
let fd = io.as_raw_fd();
let tag = context.tag();
let stream = self.0.with(move |streams| {
let item = StreamItem {
fd,
@ -84,6 +86,7 @@ impl<T: AsRawFd + 'static> StreamOps<T> {
});
self.0.api.attach(
tag,
fd,
stream.id,
Some(Event::new(0, false, false).with_interrupt()),
@ -100,19 +103,22 @@ impl<T> Clone for StreamOps<T> {
impl<T> Handler for StreamOpsHandler<T> {
fn event(&mut self, id: usize, ev: Event) {
log::debug!("FD event {:?} event: {:?}", id, ev);
self.inner.with(|streams| {
if !streams.contains(id) {
return;
}
let item = &mut streams[id];
log::debug!("{}: FD event {:?} event: {:?}", item.tag(), id, ev);
if item.flags.contains(Flags::CLOSED) {
return;
}
// handle HUP
if ev.is_interrupt() {
item.context.stopped(None);
if item.io.take().is_some() {
close(id as u32, item.fd, &self.inner.api);
close(id as u32, item, &self.inner.api);
}
return;
}
@ -157,7 +163,9 @@ impl<T> Handler for StreamOpsHandler<T> {
renew_ev.writable = true;
}
self.inner.api.modify(item.fd, id as u32, renew_ev);
self.inner
.api
.modify(item.tag(), item.fd, id as u32, renew_ev);
// delayed drops
if self.inner.delayd_drop.get() {
@ -165,7 +173,7 @@ impl<T> Handler for StreamOpsHandler<T> {
let item = &mut streams[id as usize];
item.ref_count -= 1;
if item.ref_count == 0 {
let item = streams.remove(id as usize);
let mut item = streams.remove(id as usize);
log::debug!(
"{}: Drop ({}), {:?}, has-io: {}",
item.tag(),
@ -174,7 +182,7 @@ impl<T> Handler for StreamOpsHandler<T> {
item.io.is_some()
);
if item.io.is_some() {
close(id, item.fd, &self.inner.api);
close(id, &mut item, &self.inner.api);
}
}
}
@ -189,7 +197,7 @@ impl<T> Handler for StreamOpsHandler<T> {
log::debug!("FD is failed ({}) {:?}, err: {:?}", id, item.fd, err);
item.context.stopped(Some(err));
if item.io.take().is_some() {
close(id as u32, item.fd, &self.inner.api);
close(id as u32, item, &self.inner.api);
}
}
})
@ -208,8 +216,14 @@ impl<T> StreamOpsInner<T> {
}
}
fn close(id: u32, fd: RawFd, api: &DriverApi) -> ntex_rt::JoinHandle<io::Result<i32>> {
api.detach(fd, id);
fn close<T>(
id: u32,
item: &mut StreamItem<T>,
api: &DriverApi,
) -> ntex_rt::JoinHandle<io::Result<i32>> {
let fd = item.fd;
item.flags.insert(Flags::CLOSED);
api.detach(item.tag(), fd, id);
ntex_rt::spawn_blocking(move || {
syscall!(libc::shutdown(fd, libc::SHUT_RDWR))?;
syscall!(libc::close(fd))
@ -219,16 +233,16 @@ fn close(id: u32, fd: RawFd, api: &DriverApi) -> ntex_rt::JoinHandle<io::Result<
impl<T> StreamCtl<T> {
pub(crate) fn close(self) -> impl Future<Output = io::Result<()>> {
let id = self.id as usize;
let (io, fd) = self
.inner
.with(|streams| (streams[id].io.take(), streams[id].fd));
let fut = if let Some(io) = io {
log::debug!("Closing ({}), {:?}", id, fd);
std::mem::forget(io);
Some(close(self.id, fd, &self.inner.api))
} else {
None
};
let fut = self.inner.with(|streams| {
let item = &mut streams[id];
if let Some(io) = item.io.take() {
log::debug!("{}: Closing ({}), {:?}", item.tag(), id, item.fd);
std::mem::forget(io);
Some(close(self.id, item, &self.inner.api))
} else {
None
}
});
async move {
if let Some(fut) = fut {
fut.await
@ -313,7 +327,7 @@ impl<T> StreamCtl<T> {
}
}
self.inner.api.modify(item.fd, self.id, event);
self.inner.api.modify(item.tag(), item.fd, self.id, event);
})
}
}
@ -336,7 +350,7 @@ impl<T> Drop for StreamCtl<T> {
let id = self.id as usize;
streams[id].ref_count -= 1;
if streams[id].ref_count == 0 {
let item = streams.remove(id);
let mut item = streams.remove(id);
log::debug!(
"{}: Drop io ({}), {:?}, has-io: {}",
item.tag(),
@ -345,7 +359,7 @@ impl<T> Drop for StreamCtl<T> {
item.io.is_some()
);
if item.io.is_some() {
close(self.id, item.fd, &self.inner.api);
close(self.id, &mut item, &self.inner.api);
}
}
self.inner.streams.set(Some(streams));