[libos] Fix deadlock in signal implementions

This commit is contained in:
ClawSeven 2023-12-28 15:15:11 +08:00 committed by volcano
parent e96a1348e5
commit 5d3799fcb8
4 changed files with 16 additions and 24 deletions

@ -42,21 +42,12 @@ pub fn broadcast_interrupts() -> Result<usize> {
return true;
}
let sig_mask_guard = thread.sig_mask().read().unwrap();
let interested = !*sig_mask_guard;
drop(sig_mask_guard);
let thread_pending_sig = thread.sig_queues().read().unwrap().pending() & interested;
if !thread_pending_sig.empty() {
return true;
}
let process_pending_sig =
thread.process().sig_queues().read().unwrap().pending() & interested;
if !process_pending_sig.empty() {
return true;
}
false
let interested = !*thread.sig_mask().read().unwrap();
// In the nightly-2022-10-22 Rust compiler, this expression holds two nested read locks.
// However, in the stable-2023-12-21 Rust compiler, the expression drops the temporary variables
// (including: read lock guard) after each division code completes.
!((thread.process().sig_queues().read().unwrap().pending() & interested).empty())
|| !((thread.sig_queues().read().unwrap().pending() & interested).empty())
};
let num_signaled_threads = crate::process::table::get_all_threads()

@ -6,9 +6,10 @@ pub fn do_sigpending() -> Result<SigSet> {
let thread = current!();
let process = thread.process();
let blocked = *thread.sig_mask().read().unwrap();
let pending = (thread.sig_queues().read().unwrap().pending()
| process.sig_queues().read().unwrap().pending())
& *thread.sig_mask().read().unwrap();
& blocked;
Ok(pending)
}

@ -125,12 +125,12 @@ fn do_deliver_signal(thread: &ThreadRef, process: &ProcessRef, cpu_context: &mut
let sig_mask =
*thread.sig_mask().read().unwrap() | *thread.sig_tmp_mask().read().unwrap();
let signal_opt = process
.sig_queues()
.write()
.unwrap()
.dequeue(&sig_mask)
.or_else(|| thread.sig_queues().write().unwrap().dequeue(&sig_mask));
// Don't use `Option` or_else to avoid nested write locks
let mut signal_opt = process.sig_queues().write().unwrap().dequeue(&sig_mask);
if signal_opt.is_none() {
signal_opt = thread.sig_queues().write().unwrap().dequeue(&sig_mask);
}
if signal_opt.is_none() {
return;
}

@ -163,8 +163,8 @@ impl Drop for PendingSigWaiter {
}
fn has_interest_signal(interest: &SigSet, thread: &ThreadRef, process: &ProcessRef) -> bool {
let pending = (thread.sig_queues().read().unwrap().pending()
| process.sig_queues().read().unwrap().pending())
let pending = (process.sig_queues().read().unwrap().pending()
| thread.sig_queues().read().unwrap().pending())
& *interest;
!pending.empty()