[test] Implement ut for sigsuspend
This commit is contained in:
		
							parent
							
								
									219fdd4e26
								
							
						
					
					
						commit
						e96a1348e5
					
				| @ -1152,7 +1152,6 @@ rt_sigaction03 rt_sigaction03 | |||||||
| rt_sigprocmask01 rt_sigprocmask01 | rt_sigprocmask01 rt_sigprocmask01 | ||||||
| #rt_sigprocmask02 rt_sigprocmask02 | #rt_sigprocmask02 rt_sigprocmask02 | ||||||
| rt_sigqueueinfo01 rt_sigqueueinfo01 | rt_sigqueueinfo01 rt_sigqueueinfo01 | ||||||
| rt_sigsuspend01 rt_sigsuspend01 |  | ||||||
| rt_sigtimedwait01 rt_sigtimedwait01 | rt_sigtimedwait01 rt_sigtimedwait01 | ||||||
| rt_tgsigqueueinfo01 rt_tgsigqueueinfo01 | rt_tgsigqueueinfo01 rt_tgsigqueueinfo01 | ||||||
| 
 | 
 | ||||||
| @ -1448,8 +1447,6 @@ sigprocmask01 sigprocmask01 | |||||||
| 
 | 
 | ||||||
| sigrelse01 sigrelse01 | sigrelse01 sigrelse01 | ||||||
| 
 | 
 | ||||||
| sigsuspend01 sigsuspend01 |  | ||||||
| 
 |  | ||||||
| sigtimedwait01 sigtimedwait01 | sigtimedwait01 sigtimedwait01 | ||||||
| 
 | 
 | ||||||
| sigwait01 sigwait01 | sigwait01 sigwait01 | ||||||
|  | |||||||
| @ -38,15 +38,25 @@ pub fn do_handle_interrupt( | |||||||
| /// Broadcast interrupts to threads by sending POSIX signals.
 | /// Broadcast interrupts to threads by sending POSIX signals.
 | ||||||
| pub fn broadcast_interrupts() -> Result<usize> { | pub fn broadcast_interrupts() -> Result<usize> { | ||||||
|     let should_interrupt_thread = |thread: &&ThreadRef| -> bool { |     let should_interrupt_thread = |thread: &&ThreadRef| -> bool { | ||||||
|         let should_interrupt = thread.process().is_forced_to_exit() |         if thread.process().is_forced_to_exit() || thread.is_forced_to_stop() { | ||||||
|             || thread.is_forced_to_stop() |             return true; | ||||||
|             || !thread.process().sig_queues().read().unwrap().empty(); |         } | ||||||
| 
 | 
 | ||||||
|         // Check Thread::sig_mask to avoid wrong interrupts
 |         let sig_mask_guard = thread.sig_mask().read().unwrap(); | ||||||
|         let sig_queues = thread.sig_queues().read().unwrap(); |         let interested = !*sig_mask_guard; | ||||||
|         let sig_mask = thread.sig_mask().read().unwrap(); |         drop(sig_mask_guard); | ||||||
| 
 | 
 | ||||||
|         should_interrupt || sig_queues.has_valid_signal(&sig_mask) |         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 num_signaled_threads = crate::process::table::get_all_threads() |     let num_signaled_threads = crate::process::table::get_all_threads() | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ use super::io_multiplexing::{AsEpollFile, EpollCtl, EpollFile, EpollFlags, FdSet | |||||||
| use fs::{CreationFlags, File, FileDesc, FileRef}; | use fs::{CreationFlags, File, FileDesc, FileRef}; | ||||||
| use misc::resource_t; | use misc::resource_t; | ||||||
| use process::Process; | use process::Process; | ||||||
| use signal::{do_sigprocmask, sigset_t, MaskOp, SigSet}; | use signal::{sigset_t, MaskOp, SigSet, SIGKILL, SIGSTOP}; | ||||||
| use std::convert::TryFrom; | use std::convert::TryFrom; | ||||||
| use time::{timespec_t, timeval_t}; | use time::{timespec_t, timeval_t}; | ||||||
| use util::mem_util::from_user; | use util::mem_util::from_user; | ||||||
| @ -723,9 +723,9 @@ pub fn do_select( | |||||||
|     ret |     ret | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Copy, Debug)] | #[derive(Debug)] | ||||||
| #[repr(C)] | #[repr(C)] | ||||||
| pub struct Pselect6sig { | pub struct sigset_argpack { | ||||||
|     ss: *const sigset_t, |     ss: *const sigset_t, | ||||||
|     ss_len: size_t, |     ss_len: size_t, | ||||||
| } | } | ||||||
| @ -736,11 +736,13 @@ pub fn do_pselect6( | |||||||
|     writefds: *mut libc::fd_set, |     writefds: *mut libc::fd_set, | ||||||
|     exceptfds: *mut libc::fd_set, |     exceptfds: *mut libc::fd_set, | ||||||
|     timeout: *mut timespec_t, |     timeout: *mut timespec_t, | ||||||
|     sig_data: *const Pselect6sig, |     sig_data: *const sigset_argpack, | ||||||
| ) -> Result<isize> { | ) -> Result<isize> { | ||||||
|     let mut is_set_sig = false; |     let mut is_set_sig = false; | ||||||
|     let mut original_sig_set = sigset_t::default(); |     let mut prev_mask = SigSet::default(); | ||||||
|  |     let thread = current!(); | ||||||
| 
 | 
 | ||||||
|  |     // Set signal mask
 | ||||||
|     if !sig_data.is_null() { |     if !sig_data.is_null() { | ||||||
|         from_user::check_ptr(sig_data)?; |         from_user::check_ptr(sig_data)?; | ||||||
|         let user_sig_data = unsafe { &*(sig_data) }; |         let user_sig_data = unsafe { &*(sig_data) }; | ||||||
| @ -750,15 +752,20 @@ pub fn do_pselect6( | |||||||
|             if user_sig_data.ss_len != std::mem::size_of::<sigset_t>() { |             if user_sig_data.ss_len != std::mem::size_of::<sigset_t>() { | ||||||
|                 return_errno!(EINVAL, "unexpected sigset size"); |                 return_errno!(EINVAL, "unexpected sigset size"); | ||||||
|             } |             } | ||||||
|             let op_and_set = { |             let update_mask = { | ||||||
|                 let op = MaskOp::SetMask; |  | ||||||
|                 let sigset = user_sig_data.ss; |                 let sigset = user_sig_data.ss; | ||||||
|                 from_user::check_ptr(sigset)?; |                 from_user::check_ptr(sigset)?; | ||||||
|                 let set = unsafe { &*sigset }; |                 let set = unsafe { &*sigset }; | ||||||
|                 Some((op, set)) |                 let mut set = SigSet::from_c(unsafe { *sigset }); | ||||||
|  |                 // According to man pages, "it is not possible to block SIGKILL or SIGSTOP.
 | ||||||
|  |                 // Attempts to do so are silently ignored."
 | ||||||
|  |                 set -= SIGKILL; | ||||||
|  |                 set -= SIGSTOP; | ||||||
|  |                 set | ||||||
|             }; |             }; | ||||||
| 
 |             let mut curr_mask = thread.sig_mask().write().unwrap(); | ||||||
|             do_sigprocmask::do_rt_sigprocmask(op_and_set, Some(&mut original_sig_set))?; |             prev_mask = *curr_mask; | ||||||
|  |             *curr_mask = update_mask; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -815,12 +822,8 @@ pub fn do_pselect6( | |||||||
| 
 | 
 | ||||||
|     // Restore the original signal mask
 |     // Restore the original signal mask
 | ||||||
|     if is_set_sig { |     if is_set_sig { | ||||||
|         let op_and_set = { |         let mut curr_mask = thread.sig_mask().write().unwrap(); | ||||||
|             let op = MaskOp::SetMask; |         *curr_mask = prev_mask; | ||||||
|             let set = &original_sig_set; |  | ||||||
|             Some((op, set)) |  | ||||||
|         }; |  | ||||||
|         do_sigprocmask::do_rt_sigprocmask(op_and_set, None)?; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ret |     ret | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ pub fn do_sigpending() -> Result<SigSet> { | |||||||
| 
 | 
 | ||||||
|     let thread = current!(); |     let thread = current!(); | ||||||
|     let process = thread.process(); |     let process = thread.process(); | ||||||
|  | 
 | ||||||
|     let pending = (thread.sig_queues().read().unwrap().pending() |     let pending = (thread.sig_queues().read().unwrap().pending() | ||||||
|         | process.sig_queues().read().unwrap().pending()) |         | process.sig_queues().read().unwrap().pending()) | ||||||
|         & *thread.sig_mask().read().unwrap(); |         & *thread.sig_mask().read().unwrap(); | ||||||
|  | |||||||
| @ -2,24 +2,15 @@ use super::constants::*; | |||||||
| use super::{sigset_t, SigSet}; | use super::{sigset_t, SigSet}; | ||||||
| use crate::prelude::*; | use crate::prelude::*; | ||||||
| 
 | 
 | ||||||
| pub fn do_rt_sigprocmask( | pub fn do_rt_sigprocmask(op_and_set: Option<(MaskOp, &SigSet)>) -> Result<SigSet> { | ||||||
|     op_and_set: Option<(MaskOp, &sigset_t)>, |     debug!("do_rt_sigprocmask: op_and_set: {:?}", op_and_set,); | ||||||
|     oldset: Option<&mut sigset_t>, |  | ||||||
| ) -> Result<()> { |  | ||||||
|     debug!( |  | ||||||
|         "do_rt_sigprocmask: op_and_set: {:?}, oldset: {:?}", |  | ||||||
|         op_and_set.map(|(op, set)| (op, SigSet::from_c(*set))), |  | ||||||
|         oldset |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     let thread = current!(); |     let thread = current!(); | ||||||
|     let mut sig_mask = thread.sig_mask().write().unwrap(); |     let mut sig_mask = thread.sig_mask().write().unwrap(); | ||||||
|     if let Some(oldset) = oldset { |     let old_mask = *sig_mask; | ||||||
|         *oldset = sig_mask.to_c(); |     if let Some((op, set)) = op_and_set { | ||||||
|     } |  | ||||||
|     if let Some((op, &set)) = op_and_set { |  | ||||||
|         let set = { |         let set = { | ||||||
|             let mut set = SigSet::from_c(set); |             let mut set = *set; | ||||||
|             // According to man pages, "it is not possible to block SIGKILL or SIGSTOP.
 |             // According to man pages, "it is not possible to block SIGKILL or SIGSTOP.
 | ||||||
|             // Attempts to do so are silently ignored."
 |             // Attempts to do so are silently ignored."
 | ||||||
|             set -= SIGKILL; |             set -= SIGKILL; | ||||||
| @ -38,7 +29,7 @@ pub fn do_rt_sigprocmask( | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(old_mask) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||||||
|  | |||||||
| @ -1,36 +1,46 @@ | |||||||
| use super::do_sigprocmask::do_rt_sigprocmask; | use super::constants::*; | ||||||
| use super::do_sigtimedwait::PendingSigWaiter; | use super::do_sigtimedwait::PendingSigWaiter; | ||||||
| use super::{sigset_t, MaskOp, SigNum, SigSet, Signal}; | use super::{sigset_t, MaskOp, SigNum, SigSet, Signal}; | ||||||
| use crate::prelude::*; | use crate::prelude::*; | ||||||
| 
 | 
 | ||||||
| pub fn do_sigsuspend(mask: &sigset_t) -> Result<()> { | pub fn do_sigsuspend(mask: &SigSet) -> Result<()> { | ||||||
|     debug!("do_sigsuspend: mask: {:?}", mask); |     debug!("do_sigsuspend: mask: {:?}", mask); | ||||||
| 
 | 
 | ||||||
|     let thread = current!(); |     let thread = current!(); | ||||||
|     let process = thread.process().clone(); |     let process = thread.process().clone(); | ||||||
|     let mut original_sig_set = sigset_t::default(); |  | ||||||
| 
 | 
 | ||||||
|     // Set signal mask
 |     // Set signal mask
 | ||||||
|     let op_and_set = Some((MaskOp::SetMask, mask)); |     let update_mask = { | ||||||
|     do_rt_sigprocmask(op_and_set, Some(&mut original_sig_set))?; |         let mut set = *mask; | ||||||
|  |         // According to man pages, "it is not possible to block SIGKILL or SIGSTOP.
 | ||||||
|  |         // Attempts to do so are silently ignored."
 | ||||||
|  |         set -= SIGKILL; | ||||||
|  |         set -= SIGSTOP; | ||||||
|  |         set | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     let interest = SigSet::from_c(!*mask); |     let mut curr_mask = thread.sig_mask().write().unwrap(); | ||||||
|     let pending_sig_waiter = PendingSigWaiter::new(thread, process, interest); |     let prev_mask = *curr_mask; | ||||||
|  |     *curr_mask = update_mask; | ||||||
|  |     drop(curr_mask); | ||||||
| 
 | 
 | ||||||
|     match pending_sig_waiter.suspend() { |     // Suspend for interest signal
 | ||||||
|  |     let interest = !update_mask; | ||||||
|  |     let pending_sig_waiter = PendingSigWaiter::new(thread.clone(), process, interest); | ||||||
|  | 
 | ||||||
|  |     let err = match pending_sig_waiter.suspend() { | ||||||
|         Ok(_) => { |         Ok(_) => { | ||||||
|             // Restore the original signal mask
 |             errno!(EINTR, "Wait for EINTR signal successfully") | ||||||
|             let op_and_set = { |  | ||||||
|                 let op = MaskOp::SetMask; |  | ||||||
|                 let set = &original_sig_set; |  | ||||||
|                 Some((op, set)) |  | ||||||
|             }; |  | ||||||
|             do_rt_sigprocmask(op_and_set, None).unwrap(); |  | ||||||
|             Err(errno!(EINTR, "Wait for EINTR signal successfully")) |  | ||||||
|         } |         } | ||||||
|         Err(_) => { |         Err(_) => { | ||||||
|             // Impossible path
 |             // Impossible path
 | ||||||
|             Err(errno!(EFAULT, "No interesting, pending signal")) |             errno!(EFAULT, "No interesting, pending signal") | ||||||
|         } |         } | ||||||
|     } |     }; | ||||||
|  | 
 | ||||||
|  |     // Restore the original signal mask
 | ||||||
|  |     let mut curr_mask = thread.sig_mask().write().unwrap(); | ||||||
|  |     *curr_mask = prev_mask; | ||||||
|  | 
 | ||||||
|  |     Err(err) | ||||||
| } | } | ||||||
|  | |||||||
| @ -136,10 +136,9 @@ impl PendingSigWaiter { | |||||||
|                     if has_interest_signal(&self.interest, &self.thread, &self.process) { |                     if has_interest_signal(&self.interest, &self.thread, &self.process) { | ||||||
|                         return Ok(()); |                         return Ok(()); | ||||||
|                     } |                     } | ||||||
|                 } else { |  | ||||||
|                     // Impossible case
 |  | ||||||
|                     return Err(e); |  | ||||||
|                 } |                 } | ||||||
|  |                 // Impossible case
 | ||||||
|  |                 return Err(e); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -164,17 +163,11 @@ impl Drop for PendingSigWaiter { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn has_interest_signal(interest: &SigSet, thread: &ThreadRef, process: &ProcessRef) -> bool { | fn has_interest_signal(interest: &SigSet, thread: &ThreadRef, process: &ProcessRef) -> bool { | ||||||
|     let blocked = !*interest; |     let pending = (thread.sig_queues().read().unwrap().pending() | ||||||
|     process |         | process.sig_queues().read().unwrap().pending()) | ||||||
|         .sig_queues() |         & *interest; | ||||||
|         .write() | 
 | ||||||
|         .unwrap() |     !pending.empty() | ||||||
|         .has_valid_signal(&blocked) |  | ||||||
|         || thread |  | ||||||
|             .sig_queues() |  | ||||||
|             .write() |  | ||||||
|             .unwrap() |  | ||||||
|             .has_valid_signal(&blocked) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn dequeue_pending_signal( | fn dequeue_pending_signal( | ||||||
|  | |||||||
| @ -22,6 +22,7 @@ mod do_kill; | |||||||
| mod do_sigaction; | mod do_sigaction; | ||||||
| mod do_sigaltstack; | mod do_sigaltstack; | ||||||
| mod do_sigpending; | mod do_sigpending; | ||||||
|  | mod do_sigprocmask; | ||||||
| mod do_sigreturn; | mod do_sigreturn; | ||||||
| mod do_sigsuspend; | mod do_sigsuspend; | ||||||
| mod do_sigtimedwait; | mod do_sigtimedwait; | ||||||
| @ -35,4 +36,3 @@ mod signals; | |||||||
| mod syscalls; | mod syscalls; | ||||||
| 
 | 
 | ||||||
| pub mod constants; | pub mod constants; | ||||||
| pub mod do_sigprocmask; |  | ||||||
|  | |||||||
| @ -38,41 +38,6 @@ impl SigQueues { | |||||||
|         self.count == 0 |         self.count == 0 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn has_valid_signal(&self, blocked: &SigSet) -> bool { |  | ||||||
|         // Fast path for the common case of no pending signals
 |  | ||||||
|         if self.empty() { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Check standard signals.
 |  | ||||||
|         for &signum in &Self::ORDERED_STD_SIGS { |  | ||||||
|             if blocked.contains(signum) { |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             let queue = self.get_std_queue(signum); |  | ||||||
|             if queue.is_some() { |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // If no standard signals, then check real-time signals.
 |  | ||||||
|         for signum in MIN_RT_SIG_NUM..=MAX_RT_SIG_NUM { |  | ||||||
|             let signum = unsafe { SigNum::from_u8_unchecked(signum) }; |  | ||||||
|             if blocked.contains(signum) { |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             let queue = self.get_rt_queue(signum); |  | ||||||
|             if !queue.is_empty() { |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // There must be pending but blocked signals
 |  | ||||||
|         false |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn enqueue(&mut self, signal: Box<dyn Signal>) { |     pub fn enqueue(&mut self, signal: Box<dyn Signal>) { | ||||||
|         let signum = signal.num(); |         let signum = signal.num(); | ||||||
|         if signum.is_std() { |         if signum.is_std() { | ||||||
|  | |||||||
| @ -89,23 +89,25 @@ pub fn do_rt_sigprocmask( | |||||||
|     if sigset_size != std::mem::size_of::<sigset_t>() { |     if sigset_size != std::mem::size_of::<sigset_t>() { | ||||||
|         return_errno!(EINVAL, "unexpected sigset size"); |         return_errno!(EINVAL, "unexpected sigset size"); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     let mut set_sig = SigSet::default(); | ||||||
|     let op_and_set = { |     let op_and_set = { | ||||||
|         if !set_ptr.is_null() { |         if !set_ptr.is_null() { | ||||||
|             let op = MaskOp::from_u32(how as u32)?; |             let op = MaskOp::from_u32(how as u32)?; | ||||||
|             let set = unsafe { &*set_ptr }; |             set_sig = SigSet::from_c(unsafe { *set_ptr }); | ||||||
|             Some((op, set)) |             Some((op, &set_sig)) | ||||||
|         } else { |         } else { | ||||||
|             None |             None | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|     let old_set = { | 
 | ||||||
|         if !oldset_ptr.is_null() { |     let old_set = super::do_sigprocmask::do_rt_sigprocmask(op_and_set)?; | ||||||
|             Some(unsafe { &mut *oldset_ptr }) |     if !oldset_ptr.is_null() { | ||||||
|         } else { |         unsafe { | ||||||
|             None |             *oldset_ptr = old_set.to_c(); | ||||||
|         } |         } | ||||||
|     }; |     } | ||||||
|     super::do_sigprocmask::do_rt_sigprocmask(op_and_set, old_set)?; | 
 | ||||||
|     Ok(0) |     Ok(0) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -201,7 +203,7 @@ pub fn do_rt_sigsuspend(mask_ptr: *const sigset_t) -> Result<isize> { | |||||||
|             return_errno!(EFAULT, "ptr must not be null"); |             return_errno!(EFAULT, "ptr must not be null"); | ||||||
|         } |         } | ||||||
|         from_user::check_ptr(mask_ptr)?; |         from_user::check_ptr(mask_ptr)?; | ||||||
|         unsafe { *mask_ptr } |         SigSet::from_c(unsafe { *mask_ptr }) | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     super::do_sigsuspend::do_sigsuspend(&mask)?; |     super::do_sigsuspend::do_sigsuspend(&mask)?; | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ use crate::net::{ | |||||||
|     do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen, |     do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen, | ||||||
|     do_poll, do_ppoll, do_pselect6, do_recvfrom, do_recvmsg, do_select, do_sendmmsg, do_sendmsg, |     do_poll, do_ppoll, do_pselect6, do_recvfrom, do_recvmsg, do_select, do_sendmmsg, do_sendmsg, | ||||||
|     do_sendto, do_setsockopt, do_shutdown, do_socket, do_socketpair, mmsghdr, msghdr, msghdr_mut, |     do_sendto, do_setsockopt, do_shutdown, do_socket, do_socketpair, mmsghdr, msghdr, msghdr_mut, | ||||||
|     Pselect6sig, |     sigset_argpack, | ||||||
| }; | }; | ||||||
| use crate::process::{ | use crate::process::{ | ||||||
|     do_arch_prctl, do_clone, do_execve, do_exit, do_exit_group, do_futex, do_get_robust_list, |     do_arch_prctl, do_clone, do_execve, do_exit, do_exit_group, do_futex, do_get_robust_list, | ||||||
| @ -367,7 +367,7 @@ macro_rules! process_syscall_table_with_callback { | |||||||
|             (Readlinkat = 267) => do_readlinkat(dirfd: i32, path: *const i8, buf: *mut u8, size: usize), |             (Readlinkat = 267) => do_readlinkat(dirfd: i32, path: *const i8, buf: *mut u8, size: usize), | ||||||
|             (Fchmodat = 268) => do_fchmodat(dirfd: i32, path: *const i8, mode: u16), |             (Fchmodat = 268) => do_fchmodat(dirfd: i32, path: *const i8, mode: u16), | ||||||
|             (Faccessat = 269) => do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32), |             (Faccessat = 269) => do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32), | ||||||
|             (Pselect6 = 270) => do_pselect6(nfds: c_int, readfds: *mut libc::fd_set, writefds: *mut libc::fd_set, exceptfds: *mut libc::fd_set, timeout: *mut timespec_t, data: *const Pselect6sig), |             (Pselect6 = 270) => do_pselect6(nfds: c_int, readfds: *mut libc::fd_set, writefds: *mut libc::fd_set, exceptfds: *mut libc::fd_set, timeout: *mut timespec_t, data: *const sigset_argpack), | ||||||
|             (Ppoll = 271) => do_ppoll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout_ts: *const timespec_t, sigmask: *const sigset_t), |             (Ppoll = 271) => do_ppoll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout_ts: *const timespec_t, sigmask: *const sigset_t), | ||||||
|             (Unshare = 272) => handle_unsupported(), |             (Unshare = 272) => handle_unsupported(), | ||||||
|             (SetRobustList = 273) => do_set_robust_list(list_head_ptr: *mut RobustListHead, len: usize), |             (SetRobustList = 273) => do_set_robust_list(list_head_ptr: *mut RobustListHead, len: usize), | ||||||
|  | |||||||
| @ -21,8 +21,8 @@ TEST_DEPS := client data_sink naughty_child | |||||||
| TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time timerfd \
 | TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time timerfd \
 | ||||||
| 	truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info rlimit \
 | 	truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info rlimit \
 | ||||||
| 	server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group posix_flock \
 | 	server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group posix_flock \
 | ||||||
| 	ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait pselect \
 | 	ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs pselect sigsuspend \
 | ||||||
| 	spawn_attribute exec statfs random umask pgrp vfork mount flock utimes shm epoll brk posix_shm | 	wait spawn_attribute exec statfs random umask pgrp vfork mount flock utimes shm epoll brk posix_shm | ||||||
| # Benchmarks: need to be compiled and run by bench-% target
 | # Benchmarks: need to be compiled and run by bench-% target
 | ||||||
| BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput | BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <stdint.h> // for uint64_t | #include <stdint.h> // for uint64_t | ||||||
| #include <pthread.h> | #include <pthread.h> | ||||||
|  | #include "test.h" | ||||||
| 
 | 
 | ||||||
| // Signal handler for SIGUSR1
 | // Signal handler for SIGUSR1
 | ||||||
| void sigusr1_handler(int sig) { | void sigusr1_handler(int sig) { | ||||||
| @ -36,13 +37,13 @@ int main() { | |||||||
|     // Spawn new thread for sending signal when call pselect syscall
 |     // Spawn new thread for sending signal when call pselect syscall
 | ||||||
|     pthread_t signal_thread; |     pthread_t signal_thread; | ||||||
|     if (pthread_create(&signal_thread, NULL, send_signal, &main_thread_id) != 0) { |     if (pthread_create(&signal_thread, NULL, send_signal, &main_thread_id) != 0) { | ||||||
|         perror("pthread_create"); |         THROW_ERROR("pthread_create"); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     int timer_fd = timerfd_create(CLOCK_REALTIME, 0); |     int timer_fd = timerfd_create(CLOCK_REALTIME, 0); | ||||||
|     if (timer_fd == -1) { |     if (timer_fd == -1) { | ||||||
|         perror("timerfd_create"); |         THROW_ERROR("timerfd_create"); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -52,7 +53,7 @@ int main() { | |||||||
|     timerValue.it_interval.tv_sec = 0; |     timerValue.it_interval.tv_sec = 0; | ||||||
|     timerValue.it_interval.tv_nsec = 0; |     timerValue.it_interval.tv_nsec = 0; | ||||||
|     if (timerfd_settime(timer_fd, 0, &timerValue, NULL) == -1) { |     if (timerfd_settime(timer_fd, 0, &timerValue, NULL) == -1) { | ||||||
|         perror("timerfd_settime"); |         THROW_ERROR("timerfd_settime"); | ||||||
|         close(timer_fd); |         close(timer_fd); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| @ -63,17 +64,17 @@ int main() { | |||||||
| 
 | 
 | ||||||
|     int ready = pselect(timer_fd + 1, &readfds, NULL, NULL, NULL, &sigmask); |     int ready = pselect(timer_fd + 1, &readfds, NULL, NULL, NULL, &sigmask); | ||||||
| 
 | 
 | ||||||
|     if (ready == -1) { |     if (ready > 0) { | ||||||
|         perror("pselect6"); |  | ||||||
|     } else if (ready == 0) { |  | ||||||
|         // Impossible case
 |  | ||||||
|         printf("No input - timeout reached\n"); |  | ||||||
|     } else { |  | ||||||
|         if (FD_ISSET(timer_fd, &readfds)) { |         if (FD_ISSET(timer_fd, &readfds)) { | ||||||
|             printf("Timer expired, pselect blocked SIGUSR1 signal successfully\n"); |             printf("Timer expired, pselect blocked SIGUSR1 signal successfully\n"); | ||||||
|             uint64_t expirations; |             uint64_t expirations; | ||||||
|             read(timer_fd, &expirations, sizeof(expirations)); |             read(timer_fd, &expirations, sizeof(expirations)); | ||||||
|         } |         } | ||||||
|  |     } else if (ready == 0) { | ||||||
|  |         // Impossible case
 | ||||||
|  |         printf("No input - timeout reached\n"); | ||||||
|  |     } else { | ||||||
|  |         THROW_ERROR("failed to pselect"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pthread_join(signal_thread, NULL); |     pthread_join(signal_thread, NULL); | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								test/sigsuspend/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										5
									
								
								test/sigsuspend/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | include ../test_common.mk | ||||||
|  | 
 | ||||||
|  | EXTRA_C_FLAGS := | ||||||
|  | EXTRA_LINK_FLAGS := -lpthread | ||||||
|  | BIN_ARGS := | ||||||
							
								
								
									
										64
									
								
								test/sigsuspend/main.c
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										64
									
								
								test/sigsuspend/main.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | |||||||
|  | #include <sys/select.h> | ||||||
|  | #include <sys/timerfd.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdint.h> // for uint64_t | ||||||
|  | #include <pthread.h> | ||||||
|  | #include "test.h" | ||||||
|  | 
 | ||||||
|  | // Signal handler for SIGUSR1
 | ||||||
|  | void sigusr_handler(int sig) { | ||||||
|  |     printf("Received signals: %d. ", sig); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void *send_signal(void *arg) { | ||||||
|  |     pthread_t main_thread_id = *(pthread_t *)arg; | ||||||
|  |     sleep(1); | ||||||
|  |     pthread_kill(main_thread_id, SIGUSR1); | ||||||
|  |     sleep(1); | ||||||
|  |     pthread_kill(main_thread_id, SIGUSR2); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main() { | ||||||
|  |     // Set SIGUSR1 signal action
 | ||||||
|  |     struct sigaction sa1; | ||||||
|  |     sa1.sa_handler = sigusr_handler; | ||||||
|  |     sigemptyset(&sa1.sa_mask); | ||||||
|  |     sa1.sa_flags = 0; | ||||||
|  |     sigaction(SIGUSR1, &sa1, NULL); | ||||||
|  | 
 | ||||||
|  |     // Set SIGUSR2 signal action
 | ||||||
|  |     struct sigaction sa2; | ||||||
|  |     sa2.sa_handler = sigusr_handler; | ||||||
|  |     sigemptyset(&sa2.sa_mask); | ||||||
|  |     sa2.sa_flags = 0; | ||||||
|  |     sigaction(SIGUSR2, &sa2, NULL); | ||||||
|  | 
 | ||||||
|  |     // Mask for blocking SIGUSR1 signal
 | ||||||
|  |     sigset_t sigmask; | ||||||
|  |     sigemptyset(&sigmask); | ||||||
|  |     sigaddset(&sigmask, SIGUSR1); | ||||||
|  | 
 | ||||||
|  |     // Access pthread id
 | ||||||
|  |     pthread_t main_thread_id = pthread_self(); | ||||||
|  | 
 | ||||||
|  |     // Spawn new thread for sending signal when call pselect syscall
 | ||||||
|  |     pthread_t signal_thread; | ||||||
|  |     if (pthread_create(&signal_thread, NULL, send_signal, &main_thread_id) != 0) { | ||||||
|  |         THROW_ERROR("failed to create pthread"); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int ret = sigsuspend(&sigmask); | ||||||
|  |     if (ret == -1) { | ||||||
|  |         printf("Signal received, the rt_sigsuspend syscall returns successfully\n"); | ||||||
|  |     } else { | ||||||
|  |         THROW_ERROR("failed to call rt_sigsuspend syscall"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pthread_join(signal_thread, NULL); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user