Check only not blocked signals in Pauser

This commit is contained in:
Jianfeng Jiang
2024-05-09 06:37:13 +00:00
committed by Tate, Hongliang Tian
parent 5cde55da3d
commit 6f3a483be6
4 changed files with 41 additions and 24 deletions

View File

@ -101,8 +101,11 @@ impl PosixThread {
self.sig_queues.sig_pending()
}
pub fn has_pending_signal(&self) -> bool {
!self.sig_queues.is_empty()
/// Returns whether the thread has some pending signals
/// that are not blocked.
pub fn has_pending(&self) -> bool {
let blocked = *self.sig_mask().lock();
self.sig_queues.has_pending(blocked)
}
/// Returns whether the signal is blocked by the thread.

View File

@ -111,25 +111,28 @@ impl Pauser {
{
self.is_interrupted.store(false, Ordering::Release);
// Register observer on sigqueue
let observer = Arc::downgrade(self) as Weak<dyn Observer<SigEvents>>;
let filter = {
let sig_mask = {
let current_thread = current_thread!();
let poxis_thread = current_thread.as_posix_thread().unwrap();
let mut current_sigmask = *poxis_thread.sig_mask().lock();
current_sigmask.block(self.sig_mask.as_u64());
current_sigmask
};
SigEventsFilter::new(sig_mask)
};
let current_thread = current_thread!();
let posix_thread = current_thread.as_posix_thread().unwrap();
// Block `self.sig_mask`
let (old_mask, filter) = {
let mut current_mask = posix_thread.sig_mask().lock();
let old_mask = *current_mask;
let new_mask = {
current_mask.block(self.sig_mask.as_u64());
*current_mask
};
(old_mask, SigEventsFilter::new(new_mask))
};
// Register observer on sigqueue
let observer = Arc::downgrade(self) as Weak<dyn Observer<SigEvents>>;
posix_thread.register_sigqueue_observer(observer.clone(), filter);
// Some signal may come before we register observer, so we do another check here.
if posix_thread.has_pending_signal() {
if posix_thread.has_pending_signals() {
self.is_interrupted.store(true, Ordering::Release);
}
@ -159,6 +162,7 @@ impl Pauser {
};
posix_thread.unregiser_sigqueue_observer(&observer);
posix_thread.sig_mask().lock().set(old_mask.as_u64());
match res? {
Res::Ok(r) => Ok(r),

View File

@ -61,11 +61,17 @@ impl SigQueues {
signal
}
/// Returns the pending signals
pub fn sig_pending(&self) -> SigSet {
let queues = self.queues.lock();
queues.sig_pending()
}
/// Returns whether there's some pending signals that are not blocked
pub fn has_pending(&self, blocked: SigMask) -> bool {
self.queues.lock().has_pending(blocked)
}
pub fn register_observer(
&self,
observer: Weak<dyn Observer<SigEvents>>,
@ -189,6 +195,15 @@ impl Queues {
None
}
/// Returns whether the `SigQueues` has some pending signals which are not blocked
fn has_pending(&self, blocked: SigMask) -> bool {
self.std_queues.iter().any(|signal| {
signal
.as_ref()
.is_some_and(|signal| !blocked.contains(signal.num()))
}) || self.rt_queues.iter().any(|rt_queue| !rt_queue.is_empty())
}
fn get_std_queue_mut(&mut self, signum: SigNum) -> &mut Option<Box<dyn Signal>> {
debug_assert!(signum.is_std());
let idx = (signum.as_u8() - MIN_STD_SIG_NUM) as usize;

View File

@ -17,11 +17,6 @@ use crate::{
/// create new task with userspace and parent process
pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>) -> Arc<Task> {
fn user_task_entry() {
fn has_pending_signal(current_thread: &Arc<Thread>) -> bool {
let posix_thread = current_thread.as_posix_thread().unwrap();
posix_thread.has_pending_signal()
}
let current_thread = current_thread!();
let current_task = current_thread.task();
let user_space = current_task
@ -41,8 +36,8 @@ pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>
user_mode.context().syscall_ret()
);
#[allow(clippy::redundant_closure)]
let has_kernel_event_fn = || has_pending_signal(&current_thread);
let posix_thread = current_thread.as_posix_thread().unwrap();
let has_kernel_event_fn = || posix_thread.has_pending();
loop {
let return_reason = user_mode.execute(has_kernel_event_fn);
let context = user_mode.context_mut();
@ -52,7 +47,7 @@ pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>
ReturnReason::UserSyscall => handle_syscall(context),
ReturnReason::KernelEvent => {}
};
// should be do this comparison before handle signal?
if current_thread.status().is_exited() {
break;
}