[libos] Fix deadlock in signal implementions
This commit is contained in:
		
							parent
							
								
									2a801e5fec
								
							
						
					
					
						commit
						065c367b37
					
				| @ -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