From 6421fd0b36aafb3fcd9a8f12d5bc6e89f3f86546 Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Tue, 5 Nov 2024 17:17:40 +0800 Subject: [PATCH] Make `pause_timeout` return `EINTR` --- kernel/src/process/signal/pause.rs | 38 +++++++++++++++++++----------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/kernel/src/process/signal/pause.rs b/kernel/src/process/signal/pause.rs index f9caf4b91..d800fa51a 100644 --- a/kernel/src/process/signal/pause.rs +++ b/kernel/src/process/signal/pause.rs @@ -86,10 +86,9 @@ pub trait Pause: WaitTimeout { /// /// # Errors /// - /// This method will return an error with [`ETIME`] if the timeout is reached. - /// - /// Unlike other methods in the trait, this method will _not_ return an error with [`EINTR`] if - /// a signal is received (FIXME). + /// This method will return an error with + /// - [`EINTR`] if a signal is received; + /// - [`ETIME`] if the timeout is reached. /// /// [`ETIME`]: crate::error::Errno::ETIME /// [`EINTR`]: crate::error::Errno::EINTR @@ -108,10 +107,10 @@ impl Pause for Waiter { // No fast paths for `Waiter`. If the caller wants a fast path, it should do so _before_ // the waiter is created. - let current_thread = self.task().data().downcast_ref::>(); - - let Some(posix_thread) = current_thread - .as_ref() + let Some(posix_thread) = self + .task() + .data() + .downcast_ref::>() .and_then(|thread| thread.as_posix_thread()) else { return self.wait_until_or_timeout_cancelled(cond, || Ok(()), timeout); @@ -142,12 +141,13 @@ impl Pause for Waiter { }) }); - let current_thread = self.task().data().downcast_ref::>(); + let posix_thread_opt = self + .task() + .data() + .downcast_ref::>() + .and_then(|thread| thread.as_posix_thread()); - if let Some(posix_thread) = current_thread - .as_ref() - .and_then(|thread| thread.as_posix_thread()) - { + if let Some(posix_thread) = posix_thread_opt { posix_thread.set_signalled_waker(self.waker()); self.wait(); posix_thread.clear_signalled_waker(); @@ -157,12 +157,22 @@ impl Pause for Waiter { if let Some(timer) = timer { if timer.remain().is_zero() { - return_errno_with_message!(Errno::ETIME, "the timeout is reached"); + return_errno_with_message!(Errno::ETIME, "the time limit is reached"); } // If the timeout is not expired, cancel the timer manually. timer.cancel(); } + if posix_thread_opt + .as_ref() + .is_some_and(|posix_thread| posix_thread.has_pending()) + { + return_errno_with_message!( + Errno::EINTR, + "the current thread is interrupted by a signal" + ); + } + Ok(()) } }