[libos] Fix deadlock in signal implementions
This commit is contained in:
parent
e96a1348e5
commit
5d3799fcb8
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user