[test] Implement ut for sigsuspend
This commit is contained in:
parent
1147e6956f
commit
2a801e5fec
@ -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.
|
||||||
let interest = SigSet::from_c(!*mask);
|
// Attempts to do so are silently ignored."
|
||||||
let pending_sig_waiter = PendingSigWaiter::new(thread, process, interest);
|
set -= SIGKILL;
|
||||||
|
set -= SIGSTOP;
|
||||||
match pending_sig_waiter.suspend() {
|
set
|
||||||
Ok(_) => {
|
|
||||||
// Restore the original signal mask
|
|
||||||
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"))
|
let mut curr_mask = thread.sig_mask().write().unwrap();
|
||||||
|
let prev_mask = *curr_mask;
|
||||||
|
*curr_mask = update_mask;
|
||||||
|
drop(curr_mask);
|
||||||
|
|
||||||
|
// 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(_) => {
|
||||||
|
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,13 +136,12 @@ 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
|
// Impossible case
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for PendingSigWaiter {
|
impl Drop for PendingSigWaiter {
|
||||||
@ -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 = {
|
|
||||||
|
let old_set = super::do_sigprocmask::do_rt_sigprocmask(op_and_set)?;
|
||||||
if !oldset_ptr.is_null() {
|
if !oldset_ptr.is_null() {
|
||||||
Some(unsafe { &mut *oldset_ptr })
|
unsafe {
|
||||||
} else {
|
*oldset_ptr = old_set.to_c();
|
||||||
None
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
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