From cd369993d909aac4d30e7b2f21105fe070cd5f14 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Fri, 17 Jul 2026 06:41:01 +0700 Subject: [PATCH] Fix EOF using EVENT_TIMEOUT_ID --- src/event.rs | 52 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/event.rs b/src/event.rs index 14d38a7ed0..1b68974731 100644 --- a/src/event.rs +++ b/src/event.rs @@ -5,7 +5,7 @@ use core::{ }; use hashbrown::{hash_map::DefaultHashBuilder, HashMap}; use smallvec::SmallVec; -use syscall::{data::GlobalSchemes, EINTR}; +use syscall::{data::GlobalSchemes, EAGAIN, EINTR}; use crate::{ context, @@ -27,7 +27,7 @@ int_like!(EventQueueId, AtomicEventQueueId, usize, AtomicUsize); pub struct EventQueue { id: EventQueueId, queue: WaitQueue, - timeout_opt: Mutex>, + timeout_opt: Mutex>, } impl EventQueue { @@ -59,19 +59,45 @@ impl EventQueue { pub fn read_with_timeout( &self, buf: UserSliceWo, - timeout: u128, + timeout: usize, token: &mut CleanLockToken, ) -> Result { - context::current().write(token.token()).wake = Some(timeout); + // if zero, instant timeout + let block = timeout > 0; + if block { + let mut time = crate::time::monotonic(token); + time += timeout as u128 * 1_000_000; + context::current().write(token.token()).wake = Some(time); + } let r = self .queue - .receive_into_user(buf, true, "EventQueue::read_with_timeout", token); - let old_wake = context::current().write(token.token()).wake.take(); - // The scheduler clears `wake` on timeout - if old_wake.is_none() && r.is_err_and(|e| e.errno == EINTR) { - return Ok(0); - } - r + .receive_into_user(buf, block, "EventQueue::read_with_timeout", token); + match (r, block) { + (Ok(r), _) => return Ok(r), + (err @ Err(Error { errno: EINTR }), true) => { + let old_wake = context::current().write(token.token()).wake.take(); + // The scheduler clears `wake` on timeout + if !old_wake.is_none() { + return err; + } + // proceed writing timeout + } + (Err(Error { errno: EAGAIN }), false) => { + // proceed writing timeout + } + (err, _) => return err, + }; + + // TODO: let the scheduler write this for us? + let event = Event { + id: syscall::EVENT_TIMEOUT_ID, + // TODO: it's undefined when flags is written to EVENT_TIMEOUT_ID + flags: EventFlags::EVENT_READ, + data: timeout, + }; + + let bytes_copied = buf.copy_common_bytes_from_slice(&event)?; + return Ok(bytes_copied); } pub fn write(&self, events: &[Event], token: &mut CleanLockToken) -> Result { @@ -80,9 +106,7 @@ impl EventQueue { if event.flags.is_empty() { self.timeout_opt.lock(token.token()).take(); } else { - let mut time = crate::time::monotonic(token); - time += (event.data * 1_000_000) as u128; - *self.timeout_opt.lock(token.token()) = Some(time); + *self.timeout_opt.lock(token.token()) = Some(event.data); } continue;