mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Add syscall rt_sigpending
This commit is contained in:
parent
6c34db52b3
commit
901bccadfe
@ -147,7 +147,7 @@ provided by Linux on x86-64 architecture.
|
||||
| 124 | getsid | ✅ |
|
||||
| 125 | capget | ❌ |
|
||||
| 126 | capset | ❌ |
|
||||
| 127 | rt_sigpending | ❌ |
|
||||
| 127 | rt_sigpending | ✅ |
|
||||
| 128 | rt_sigtimedwait | ❌ |
|
||||
| 129 | rt_sigqueueinfo | ❌ |
|
||||
| 130 | rt_sigsuspend | ✅ |
|
||||
|
@ -8,8 +8,11 @@ use super::{
|
||||
do_exit_group,
|
||||
kill::SignalSenderIds,
|
||||
signal::{
|
||||
sig_mask::SigMask, sig_num::SigNum, sig_queues::SigQueues, signals::Signal, SigEvents,
|
||||
SigEventsFilter, SigStack,
|
||||
sig_mask::{SigMask, SigSet},
|
||||
sig_num::SigNum,
|
||||
sig_queues::SigQueues,
|
||||
signals::Signal,
|
||||
SigEvents, SigEventsFilter, SigStack,
|
||||
},
|
||||
Credentials, Process, TermStatus,
|
||||
};
|
||||
@ -82,6 +85,10 @@ impl PosixThread {
|
||||
&self.sig_mask
|
||||
}
|
||||
|
||||
pub fn sig_pending(&self) -> SigSet {
|
||||
self.sig_queues.sig_pending()
|
||||
}
|
||||
|
||||
pub fn has_pending_signal(&self) -> bool {
|
||||
!self.sig_queues.is_empty()
|
||||
}
|
||||
|
@ -3,9 +3,12 @@
|
||||
use super::{constants::MIN_STD_SIG_NUM, sig_num::SigNum};
|
||||
use crate::prelude::*;
|
||||
|
||||
/// A signal mask.
|
||||
pub type SigMask = SigSet;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct SigMask {
|
||||
pub struct SigSet {
|
||||
bits: u64,
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,11 @@
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use super::{
|
||||
constants::*, sig_mask::SigMask, sig_num::SigNum, signals::Signal, SigEvents, SigEventsFilter,
|
||||
constants::*,
|
||||
sig_mask::{SigMask, SigSet},
|
||||
sig_num::SigNum,
|
||||
signals::Signal,
|
||||
SigEvents, SigEventsFilter,
|
||||
};
|
||||
use crate::{
|
||||
events::{Observer, Subject},
|
||||
@ -57,6 +61,11 @@ impl SigQueues {
|
||||
signal
|
||||
}
|
||||
|
||||
pub fn sig_pending(&self) -> SigSet {
|
||||
let queues = self.queues.lock();
|
||||
queues.sig_pending()
|
||||
}
|
||||
|
||||
pub fn register_observer(
|
||||
&self,
|
||||
observer: Weak<dyn Observer<SigEvents>>,
|
||||
@ -191,4 +200,24 @@ impl Queues {
|
||||
let idx = (signum.as_u8() - MIN_RT_SIG_NUM) as usize;
|
||||
&mut self.rt_queues[idx]
|
||||
}
|
||||
|
||||
fn sig_pending(&self) -> SigSet {
|
||||
let mut pending = SigSet::new_empty();
|
||||
|
||||
// Process standard signal queues
|
||||
for (idx, signal) in self.std_queues.iter().enumerate() {
|
||||
if signal.is_some() {
|
||||
pending.add_signal(SigNum::from_u8(idx as u8 + MIN_STD_SIG_NUM));
|
||||
}
|
||||
}
|
||||
|
||||
// Process real-time signal queues
|
||||
for (idx, signals) in self.rt_queues.iter().enumerate() {
|
||||
if !signals.is_empty() {
|
||||
pending.add_signal(SigNum::from_u8(idx as u8 + MIN_RT_SIG_NUM));
|
||||
}
|
||||
}
|
||||
|
||||
pending
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ use crate::syscall::{
|
||||
rename::{sys_rename, sys_renameat},
|
||||
rmdir::sys_rmdir,
|
||||
rt_sigaction::sys_rt_sigaction,
|
||||
rt_sigpending::sys_rt_sigpending,
|
||||
rt_sigprocmask::sys_rt_sigprocmask,
|
||||
rt_sigreturn::sys_rt_sigreturn,
|
||||
rt_sigsuspend::sys_rt_sigsuspend,
|
||||
@ -208,6 +209,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
||||
SYS_SETFSUID = 122 => sys_setfsuid(args[..1]);
|
||||
SYS_SETFSGID = 123 => sys_setfsgid(args[..1]);
|
||||
SYS_GETSID = 124 => sys_getsid(args[..1]);
|
||||
SYS_RT_SIGPENDING = 127 => sys_rt_sigpending(args[..2]);
|
||||
SYS_RT_SIGSUSPEND = 130 => sys_rt_sigsuspend(args[..2]);
|
||||
SYS_SIGALTSTACK = 131 => sys_sigaltstack(args[..2]);
|
||||
SYS_STATFS = 137 => sys_statfs(args[..2]);
|
||||
|
@ -76,6 +76,7 @@ mod recvfrom;
|
||||
mod rename;
|
||||
mod rmdir;
|
||||
mod rt_sigaction;
|
||||
mod rt_sigpending;
|
||||
mod rt_sigprocmask;
|
||||
mod rt_sigreturn;
|
||||
mod rt_sigsuspend;
|
||||
|
30
kernel/aster-nix/src/syscall/rt_sigpending.rs
Normal file
30
kernel/aster-nix/src/syscall/rt_sigpending.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{prelude::*, process::posix_thread::PosixThreadExt, util::write_val_to_user};
|
||||
|
||||
pub fn sys_rt_sigpending(u_set_ptr: Vaddr, sigset_size: usize) -> Result<SyscallReturn> {
|
||||
debug!(
|
||||
"u_set_ptr = 0x{:x}, sigset_size = {}",
|
||||
u_set_ptr, sigset_size
|
||||
);
|
||||
if sigset_size != 8 {
|
||||
return_errno_with_message!(Errno::EINVAL, "sigset size is not equal to 8")
|
||||
}
|
||||
do_rt_sigpending(u_set_ptr, sigset_size)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
fn do_rt_sigpending(set_ptr: Vaddr, sigset_size: usize) -> Result<()> {
|
||||
let current_thread = current_thread!();
|
||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||
|
||||
let combined_signals = {
|
||||
let sig_mask_value = posix_thread.sig_mask().lock().as_u64();
|
||||
let sig_pending_value = posix_thread.sig_pending().as_u64();
|
||||
sig_mask_value & sig_pending_value
|
||||
};
|
||||
|
||||
write_val_to_user(set_ptr, &combined_signals)?;
|
||||
Ok(())
|
||||
}
|
@ -364,6 +364,95 @@ int test_sigaltstack()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test sigpending
|
||||
// ============================================================================
|
||||
int test_sigpending()
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Set up signal handler for SIGSEGV and SIGIO
|
||||
struct sigaction new_action, old_sigsegv_action, old_sigio_action;
|
||||
memset(&new_action, 0, sizeof(struct sigaction));
|
||||
memset(&old_sigsegv_action, 0, sizeof(struct sigaction));
|
||||
new_action.sa_sigaction = handle_sigsegv;
|
||||
new_action.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGSEGV, &new_action, &old_sigsegv_action) < 0) {
|
||||
THROW_ERROR("registering new signal handler failed");
|
||||
}
|
||||
if (old_sigsegv_action.sa_handler != SIG_DFL) {
|
||||
THROW_ERROR("unexpected old sig handler");
|
||||
}
|
||||
|
||||
memset(&new_action, 0, sizeof(struct sigaction));
|
||||
memset(&old_sigio_action, 0, sizeof(struct sigaction));
|
||||
new_action.sa_sigaction = handle_sigio;
|
||||
new_action.sa_flags = SA_SIGINFO | SA_NODEFER;
|
||||
if (sigaction(SIGIO, &new_action, &old_sigio_action) < 0) {
|
||||
THROW_ERROR("registering new signal handler failed");
|
||||
}
|
||||
if (old_sigio_action.sa_handler != SIG_DFL) {
|
||||
THROW_ERROR("unexpected old sig handler");
|
||||
}
|
||||
|
||||
// Block SIGSEGV and SIGIO
|
||||
sigset_t new_set, old_set, pending_set;
|
||||
sigfillset(&new_set);
|
||||
sigaddset(&new_set, SIGSEGV);
|
||||
sigaddset(&new_set, SIGIO);
|
||||
if ((ret = sigprocmask(SIG_BLOCK, &new_set, &old_set)) < 0) {
|
||||
THROW_ERROR("sigprocmask failed unexpectedly");
|
||||
}
|
||||
|
||||
// Send SIGSEGV and SIGIO signals to the current process twice
|
||||
kill(getpid(), SIGSEGV);
|
||||
kill(getpid(), SIGSEGV); // Repeat
|
||||
kill(getpid(), SIGIO);
|
||||
kill(getpid(), SIGIO); // Repeat
|
||||
|
||||
// Check for pending signals
|
||||
if (sigpending(&pending_set) < 0) {
|
||||
THROW_ERROR("sigpending failed unexpectedly");
|
||||
}
|
||||
|
||||
if (!sigismember(&pending_set, SIGSEGV)) {
|
||||
THROW_ERROR("SIGSEGV is not pending");
|
||||
}
|
||||
|
||||
if (!sigismember(&pending_set, SIGIO)) {
|
||||
THROW_ERROR("SIGIO (real-time signal) is not pending");
|
||||
}
|
||||
|
||||
// Unblock all signals and check if pending signals are cleared
|
||||
if (sigprocmask(SIG_SETMASK, &old_set, NULL) < 0) {
|
||||
THROW_ERROR(
|
||||
"sigprocmask failed unexpectedly, failed to restore signal mask");
|
||||
}
|
||||
|
||||
// Fetch and check pending signals after unblocking
|
||||
if (sigpending(&pending_set) < 0) {
|
||||
THROW_ERROR("sigpending failed unexpectedly");
|
||||
}
|
||||
|
||||
if (sigismember(&pending_set, SIGSEGV)) {
|
||||
THROW_ERROR("SIGSEGV is pending");
|
||||
}
|
||||
|
||||
if (sigismember(&pending_set, SIGIO)) {
|
||||
THROW_ERROR("SIGIO (real-time signal) is pending");
|
||||
}
|
||||
|
||||
// Restore old sigaction
|
||||
if (sigaction(SIGSEGV, &old_sigsegv_action, NULL) < 0) {
|
||||
THROW_ERROR("restoring old signal handler failed");
|
||||
}
|
||||
if (sigaction(SIGIO, &old_sigio_action, NULL) < 0) {
|
||||
THROW_ERROR("restoring old signal handler failed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_sigprocmask();
|
||||
@ -372,5 +461,6 @@ int main()
|
||||
test_handle_sigsegv();
|
||||
test_sigchld();
|
||||
test_sigaltstack();
|
||||
test_sigpending();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user