Skip to content
Snippets Groups Projects
Verified Commit 7d562920 authored by Jacob Lorentzon's avatar Jacob Lorentzon
Browse files

Add sigaction boilerplate.

parent 98ac085c
No related branches found
No related tags found
1 merge request!480Refactor redox runtime and impl signals in userspace
......@@ -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;
......
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 {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment