Add sigaction boilerplate.
This commit is contained in:
+65
-19
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user