mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26: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 | ✅ |
|
| 124 | getsid | ✅ |
|
||||||
| 125 | capget | ❌ |
|
| 125 | capget | ❌ |
|
||||||
| 126 | capset | ❌ |
|
| 126 | capset | ❌ |
|
||||||
| 127 | rt_sigpending | ❌ |
|
| 127 | rt_sigpending | ✅ |
|
||||||
| 128 | rt_sigtimedwait | ❌ |
|
| 128 | rt_sigtimedwait | ❌ |
|
||||||
| 129 | rt_sigqueueinfo | ❌ |
|
| 129 | rt_sigqueueinfo | ❌ |
|
||||||
| 130 | rt_sigsuspend | ✅ |
|
| 130 | rt_sigsuspend | ✅ |
|
||||||
|
@ -8,8 +8,11 @@ use super::{
|
|||||||
do_exit_group,
|
do_exit_group,
|
||||||
kill::SignalSenderIds,
|
kill::SignalSenderIds,
|
||||||
signal::{
|
signal::{
|
||||||
sig_mask::SigMask, sig_num::SigNum, sig_queues::SigQueues, signals::Signal, SigEvents,
|
sig_mask::{SigMask, SigSet},
|
||||||
SigEventsFilter, SigStack,
|
sig_num::SigNum,
|
||||||
|
sig_queues::SigQueues,
|
||||||
|
signals::Signal,
|
||||||
|
SigEvents, SigEventsFilter, SigStack,
|
||||||
},
|
},
|
||||||
Credentials, Process, TermStatus,
|
Credentials, Process, TermStatus,
|
||||||
};
|
};
|
||||||
@ -82,6 +85,10 @@ impl PosixThread {
|
|||||||
&self.sig_mask
|
&self.sig_mask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sig_pending(&self) -> SigSet {
|
||||||
|
self.sig_queues.sig_pending()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_pending_signal(&self) -> bool {
|
pub fn has_pending_signal(&self) -> bool {
|
||||||
!self.sig_queues.is_empty()
|
!self.sig_queues.is_empty()
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,12 @@
|
|||||||
use super::{constants::MIN_STD_SIG_NUM, sig_num::SigNum};
|
use super::{constants::MIN_STD_SIG_NUM, sig_num::SigNum};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// A signal mask.
|
||||||
|
pub type SigMask = SigSet;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Pod)]
|
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SigMask {
|
pub struct SigSet {
|
||||||
bits: u64,
|
bits: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,11 @@
|
|||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
use super::{
|
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::{
|
use crate::{
|
||||||
events::{Observer, Subject},
|
events::{Observer, Subject},
|
||||||
@ -57,6 +61,11 @@ impl SigQueues {
|
|||||||
signal
|
signal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sig_pending(&self) -> SigSet {
|
||||||
|
let queues = self.queues.lock();
|
||||||
|
queues.sig_pending()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn register_observer(
|
pub fn register_observer(
|
||||||
&self,
|
&self,
|
||||||
observer: Weak<dyn Observer<SigEvents>>,
|
observer: Weak<dyn Observer<SigEvents>>,
|
||||||
@ -191,4 +200,24 @@ impl Queues {
|
|||||||
let idx = (signum.as_u8() - MIN_RT_SIG_NUM) as usize;
|
let idx = (signum.as_u8() - MIN_RT_SIG_NUM) as usize;
|
||||||
&mut self.rt_queues[idx]
|
&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},
|
rename::{sys_rename, sys_renameat},
|
||||||
rmdir::sys_rmdir,
|
rmdir::sys_rmdir,
|
||||||
rt_sigaction::sys_rt_sigaction,
|
rt_sigaction::sys_rt_sigaction,
|
||||||
|
rt_sigpending::sys_rt_sigpending,
|
||||||
rt_sigprocmask::sys_rt_sigprocmask,
|
rt_sigprocmask::sys_rt_sigprocmask,
|
||||||
rt_sigreturn::sys_rt_sigreturn,
|
rt_sigreturn::sys_rt_sigreturn,
|
||||||
rt_sigsuspend::sys_rt_sigsuspend,
|
rt_sigsuspend::sys_rt_sigsuspend,
|
||||||
@ -208,6 +209,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||||||
SYS_SETFSUID = 122 => sys_setfsuid(args[..1]);
|
SYS_SETFSUID = 122 => sys_setfsuid(args[..1]);
|
||||||
SYS_SETFSGID = 123 => sys_setfsgid(args[..1]);
|
SYS_SETFSGID = 123 => sys_setfsgid(args[..1]);
|
||||||
SYS_GETSID = 124 => sys_getsid(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_RT_SIGSUSPEND = 130 => sys_rt_sigsuspend(args[..2]);
|
||||||
SYS_SIGALTSTACK = 131 => sys_sigaltstack(args[..2]);
|
SYS_SIGALTSTACK = 131 => sys_sigaltstack(args[..2]);
|
||||||
SYS_STATFS = 137 => sys_statfs(args[..2]);
|
SYS_STATFS = 137 => sys_statfs(args[..2]);
|
||||||
|
@ -76,6 +76,7 @@ mod recvfrom;
|
|||||||
mod rename;
|
mod rename;
|
||||||
mod rmdir;
|
mod rmdir;
|
||||||
mod rt_sigaction;
|
mod rt_sigaction;
|
||||||
|
mod rt_sigpending;
|
||||||
mod rt_sigprocmask;
|
mod rt_sigprocmask;
|
||||||
mod rt_sigreturn;
|
mod rt_sigreturn;
|
||||||
mod rt_sigsuspend;
|
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;
|
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()
|
int main()
|
||||||
{
|
{
|
||||||
test_sigprocmask();
|
test_sigprocmask();
|
||||||
@ -372,5 +461,6 @@ int main()
|
|||||||
test_handle_sigsegv();
|
test_handle_sigsegv();
|
||||||
test_sigchld();
|
test_sigchld();
|
||||||
test_sigaltstack();
|
test_sigaltstack();
|
||||||
|
test_sigpending();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user