Add sigaction boilerplate.

This commit is contained in:
4lDO2
2024-06-20 14:21:11 +02:00
parent 98ac085c5d
commit 7d562920c2
3 changed files with 128 additions and 30 deletions
+65 -19
View File
@@ -2,7 +2,7 @@ use core::cell::Cell;
use core::ffi::c_int;
use core::sync::atomic::{AtomicU64, Ordering};
use syscall::{Result, Sigcontrol, SIGCHLD, SIGCONT, SIGURG, SIGWINCH};
use syscall::{Error, Result, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH};
use crate::arch::*;
use crate::sync::Mutex;
@@ -101,6 +101,54 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32
Ok(())
}
#[derive(Clone, Copy)]
pub enum Sigaction {
Default,
Ignore,
Handled {
handler: SignalHandler,
mask: u64,
flags: SigactionFlags,
},
}
pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> {
if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) {
return Err(Error::new(EINVAL));
}
let _sigguard = tmp_disable_signals();
let ctl = current_sigctl();
let guard = SIGACTIONS.lock();
let old_ignmask = IGNMASK.load(Ordering::Relaxed);
if let Some(old) = old {
}
let Some(new) = new else {
return Ok(());
};
match (usize::from(signal), new) {
(_, Sigaction::Ignore) | (SIGCHLD | SIGURG | SIGWINCH, Sigaction::Default) => {
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
// mark the signal as masked
ctl.word[usize::from(signal) / 32].fetch_or(1 << ((signal - 1) % 32), Ordering::Relaxed);
// POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
// sigaction.
// TODO: handle tmp_disable_signals
}
(SIGTSTP, Sigaction::Default) => (), // stop
(SIGTTIN, Sigaction::Default) => (), // stop
(SIGTTOU, Sigaction::Default) => (), // stop
(_, Sigaction::Default) => (),
(_, Sigaction::Handled { .. }) => (),
}
todo!()
}
extern "C" {
pub fn __relibc_internal_get_sigcontrol_addr() -> &'static Sigcontrol;
}
@@ -137,16 +185,18 @@ impl Drop for TmpDisableSignalsGuard {
}
}
#[derive(Clone, Copy)]
struct SignalAction {
handler: SignalHandler,
flags: SigactionFlags,
mask: u64,
}
bitflags::bitflags! {
// Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion.
#[derive(Clone, Copy)]
struct SigactionFlags: u32 {
const SA_RESETHAND = 1;
pub struct SigactionFlags: u32 {
const NOCLDSTOP = 1;
const NOCLDWAIT = 2;
const SIGINFO = 4;
const RESTORER = 0x0400_0000;
const ONSTACK = 0x0800_0000;
const RESTART = 0x1000_0000;
const NODEFER = 0x4000_0000;
const RESETHAND = 0x8000_0000;
}
}
fn default_term_handler(sig: c_int) {
@@ -161,22 +211,18 @@ fn stop_handler_sentinel(_: c_int) {
}
#[derive(Clone, Copy)]
union SignalHandler {
sa_handler: Option<extern "C" fn(c_int)>,
sa_sigaction: Option<unsafe extern "C" fn(c_int, *const (), *mut ())>,
pub union SignalHandler {
pub handler: Option<extern "C" fn(c_int)>,
pub sigaction: Option<unsafe extern "C" fn(c_int, *const (), *mut ())>,
}
struct TheDefault {
actions: [SignalAction; 64],
actions: [Sigaction; 64],
ignmask: u64,
}
static SIGACTIONS: Mutex<[SignalAction; 64]> = Mutex::new([SignalAction {
handler: SignalHandler { sa_handler: None },
flags: SigactionFlags::empty(),
mask: 0,
}; 64]);
static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH) | sig_bit(SIGCONT));
static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction::Default; 64]);
static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH));
fn expand_mask(mask: u64) -> [u64; 2] {
[mask & 0xffff_ffff, mask >> 32]
+8 -8
View File
@@ -69,14 +69,14 @@ pub const NSIG: usize = 32;
pub const SIGRTMIN: usize = 35;
pub const SIGRTMAX: usize = 64;
pub const SA_NOCLDSTOP: usize = 0x00000001;
pub const SA_NOCLDWAIT: usize = 0x00000002;
pub const SA_SIGINFO: usize = 0x00000004;
pub const SA_RESTORER: usize = 0x04000000;
pub const SA_ONSTACK: usize = 0x08000000;
pub const SA_RESTART: usize = 0x10000000;
pub const SA_NODEFER: usize = 0x40000000;
pub const SA_RESETHAND: usize = 0x80000000;
pub const SA_NOCLDSTOP: usize = 0x0000_0001;
pub const SA_NOCLDWAIT: usize = 0x0000_0002;
pub const SA_SIGINFO: usize = 0x0000_0004;
pub const SA_RESTORER: usize = 0x0400_0000;
pub const SA_ONSTACK: usize = 0x0800_0000;
pub const SA_RESTART: usize = 0x1000_0000;
pub const SA_NODEFER: usize = 0x4000_0000;
pub const SA_RESETHAND: usize = 0x8000_0000;
pub const SS_ONSTACK: usize = 0x00000001;
pub const SS_DISABLE: usize = 0x00000002;
+55 -3
View File
@@ -1,4 +1,5 @@
use core::mem;
use redox_rt::signal::{Sigaction, SigactionFlags, SignalHandler};
use syscall::{self, Result};
use super::{
@@ -8,7 +9,7 @@ use super::{
use crate::{
header::{
errno::{EINVAL, ENOSYS},
signal::{sigaction, siginfo_t, sigset_t, stack_t, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK},
signal::{sigaction, siginfo_t, sigset_t, stack_t, SA_SIGINFO, SIG_BLOCK, SIG_DFL, SIG_IGN, SIG_SETMASK, SIG_UNBLOCK},
sys_time::{itimerval, ITIMER_REAL},
time::timespec,
},
@@ -104,8 +105,59 @@ impl PalSignal for Sys {
0
}
fn sigaction(sig: c_int, act: Option<&sigaction>, oact: Option<&mut sigaction>) -> Result<(), Errno> {
todo!()
fn sigaction(sig: c_int, c_act: Option<&sigaction>, c_oact: Option<&mut sigaction>) -> Result<(), Errno> {
let sig = u8::try_from(sig).map_err(|_| syscall::Error::new(syscall::EINVAL))?;
let new_action = c_act.map(|c_act| {
let handler = c_act.sa_handler.map_or(0, |f| f as usize);
if handler == SIG_DFL {
Sigaction::Default
} else if handler == SIG_IGN {
Sigaction::Ignore
} else {
Sigaction::Handled {
handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as u64 != 0 {
SignalHandler { sigaction: unsafe { core::mem::transmute(c_act.sa_handler) } }
} else {
SignalHandler { handler: c_act.sa_handler }
},
mask: c_act.sa_mask,
flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
}
}
});
let mut old_action = c_oact.as_ref().map(|_| Sigaction::Default);
redox_rt::signal::sigaction(sig, new_action.as_ref(), old_action.as_mut())?;
if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) {
*c_oact = match old_action {
Sigaction::Ignore => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
sa_flags: 0,
sa_restorer: None,
sa_mask: 0,
},
Sigaction::Default => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_DFL) },
sa_flags: 0,
sa_restorer: None,
sa_mask: 0,
},
Sigaction::Handled { handler, mask, flags } => sigaction {
sa_handler: if flags.contains(SigactionFlags::SIGINFO) {
unsafe { core::mem::transmute(handler.sigaction) }
} else {
unsafe { handler.handler }
},
sa_restorer: None,
sa_flags: flags.bits().into(),
sa_mask: mask,
},
};
}
Ok(())
}
unsafe fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {