Commit 6401a5ac authored by Nifou's avatar Nifou

Add a signal mask of blocked signals for each process

parent 59e0bcc2
Pipeline #173686092 passed with stages
in 9 minutes and 20 seconds
......@@ -30,7 +30,7 @@ use crate::tasking::{
process::{Pid, NEXT_PID},
scheduler::{exit, PROCESSES, SCHEDULER},
thread::Thread,
signal::{Signal, SigAction, SI_TKILL, SigInfo, send_signal_to},
signal::{Signal, SigAction, SigActionFlags, SI_TKILL, SigInfo, SigMask, send_signal_to, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK},
};
impl Syscall {
......@@ -106,12 +106,22 @@ impl Syscall {
let process = processes.get_mut(&thread.process).unwrap();
let action = if action > 0 {
Some(unsafe { &*(action as *const SigAction) })
let mut val = unsafe { &mut *(action as *mut SigAction) };
// Dereference the `mask` pointer
val.sa_mask = unsafe { *(&val.sa_mask as *const SigMask) };
Some(val)
} else {
None
};
let oldaction = if oldaction > 0 {
Some(unsafe { &mut *(oldaction as *mut SigAction) })
let mut val = unsafe { &mut *(oldaction as *mut SigAction) };
// Dereference the `mask` pointer
val.sa_mask = unsafe { *(&val.sa_mask as *const SigMask) };
Some(val)
} else {
None
};
......@@ -144,23 +154,82 @@ impl Syscall {
/// Change the mask of blocked signals
pub fn sigprocmask(&self, how: usize, set: usize, oldset: usize, size: usize) -> Result {
/* TODO: Set signal mask*/
let mut processes = PROCESSES.write();
let thread = SCHEDULER.get().current().unwrap();
let process = processes.get_mut(&thread.process).unwrap();
let set = if set > 0 {
Some(unsafe { *(set as *const SigMask) })
} else {
None
};
let oldset = if oldset > 0 {
Some(unsafe { &mut *(oldset as *mut SigMask) })
} else {
None
};
println!(
"sigprocmask({}, {:#x}, {:#x}, {}) = 0",
how, set, oldset, size
"sigprocmask({}, {}{:?}, {:?}, {}) = 0",
match how {
SIG_BLOCK => "SIG_BLOCK",
SIG_UNBLOCK => "SIG_UNBLOCK",
SIG_SETMASK => "SIG_SETMASK",
_ => "",
},
match how {
SIG_BLOCK => "~ ",
SIG_UNBLOCK => "&! ",
SIG_SETMASK => "= ",
_ => "",
},
match how {
// Display the opposite for SIG_BLOCK
SIG_BLOCK => if let Some(set) = set { Some(!set) } else { None },
_ => set,
}, oldset, size
);
if oldset.is_some() {
*oldset.unwrap() = process.signal_mask;
}
if let Some(set) = set {
// Make sure that neither SIGKILL nor SIGSTOP are present
let mut set = set.clone();
set.remove(SigMask::SIGKILL);
set.remove(SigMask::SIGSTOP);
match how {
SIG_BLOCK => process.signal_mask.insert(set),
SIG_UNBLOCK => process.signal_mask.remove(set),
SIG_SETMASK => process.signal_mask = set,
_ => return Err(Error::EINVAL),
}
}
Ok(0)
}
/// Restore the context before the signal handler
pub fn sigreturn(&mut self) -> Result {
let processes = PROCESSES.read();
let mut processes = PROCESSES.write();
let current = SCHEDULER.get().current().unwrap().process;
let process = &processes.get(&current).unwrap();
assert!(process.signal_context.is_some());
let process = processes.get_mut(&current).unwrap();
*self.stack = process.signal_context.unwrap();
Ok(0)
assert!(process.signal_saved.is_some());
let saved = process.signal_saved.take().unwrap();
println!("sigreturn() = 0");
// Unblock the current signal if SA_NODEFER is not set
if !saved.2.sa_flags.contains(SigActionFlags::SA_NODEFER) {
process.signal_mask.remove(SigMask::from(saved.1));
}
*self.stack = saved.0;
Ok(saved.0.rax)
}
/// Wait for a process to change state
......
......@@ -21,7 +21,7 @@ use super::{
thread::{Thread, Tid},
context::Fx,
scheduler::PROCESSES,
signal::{DEFAULT_ACTIONS, SIGDFL, SIGIGN, SigActionFlags, SigInfo},
signal::{DEFAULT_ACTIONS, SIGDFL, SIGIGN, SigActionFlags, SigInfo, SigMask},
info::StackWriter,
};
......@@ -59,12 +59,6 @@ pub trait SchedulerAlgo {
let mut processes = PROCESSES.write();
let process = processes.get_mut(&thread.process).unwrap();
if process.signal_context.is_some() {
// A signal handler was executed and is terminated. We need to restore the
// context before the execution
*thread.get_kstack() = process.signal_context.unwrap();
}
if !process.signals.is_empty() {
// --- Handles signals ---
let signal = process.signals.pop_front().unwrap();
......@@ -78,6 +72,11 @@ pub trait SchedulerAlgo {
// If the action is a default action, do it in kernel mode, so here
let handler = DEFAULT_ACTIONS.get(&signal.0).unwrap().sa_handler;
// Block the current signal if SA_NODEFER is not set
if !action.sa_flags.contains(SigActionFlags::SA_NODEFER) {
process.signal_mask.insert(SigMask::from(signal.0));
}
drop(processes);
unsafe { transmute::<*const (), fn()>(handler as *const ())(); }
......@@ -88,7 +87,7 @@ pub trait SchedulerAlgo {
let kstack = thread.get_kstack();
// Save the context
process.signal_context = Some(*kstack);
process.signal_saved = Some((*kstack, signal.0, *action));
// TODO: Save and restore the SSE state
// Change the instruction pointer
......@@ -101,6 +100,11 @@ pub trait SchedulerAlgo {
kstack.rsp = process.signal_stack.expect("the signal stack must be initialized") as usize;
}
// Block the current signal if SA_NODEFER is not set
if !action.sa_flags.contains(SigActionFlags::SA_NODEFER) {
process.signal_mask.insert(SigMask::from(signal.0));
}
// Save utilities before the drop of the lock
let mem = process.memory.clone();
let action = action.clone();
......
......@@ -24,7 +24,7 @@ use super::{
memory::{MemoryArea, ProcessMemory},
scheduler::{PROCESSES, SCHEDULER},
thread::{Thread, Tid},
signal::{SignalQueue, SigActions},
signal::{SignalQueue, SigActions, SigMask, Signal, SigAction},
context::Registers,
};
use crate::memory::{self, PAGE_SIZE};
......@@ -100,8 +100,13 @@ pub struct Process {
/// The stack used when a signal happens
pub signal_stack: Option<u64>,
/// The saved context before the execution of the signal handler
pub signal_context: Option<Registers>,
/// The saved things before the execution of the signal handler
/// * The context
/// * The signal's action
pub signal_saved: Option<(Registers, Signal, SigAction)>,
/// The signal mask for blocked signals
pub signal_mask: SigMask,
}
impl Process {
......@@ -120,7 +125,8 @@ impl Process {
signals: SignalQueue::new(),
actions: SigActions::default(),
signal_stack: None,
signal_context: None,
signal_saved: None,
signal_mask: SigMask::empty(),
}
}
......
......@@ -101,10 +101,11 @@ pub enum Signal {
/// Signals that the process should terminate (unlike SIGKILL, it can clean-up)
SIGTERM,
// SIGSTKFLT is ignored in Linux
/// Signals a stack overflow
SIGSTKFLT,
/// Signals that a child process is terminated
SIGCHLD = 17,
SIGCHLD,
/// Resumes a stopped process
SIGCONT,
......@@ -172,7 +173,7 @@ bitflags! {
/// Is an interrupted syscall need to be restarted
const SA_RESTART = 1 << 28;
/// TODO
/// Prevent the signal from being masked in the handler
const SA_NODEFER = 1 << 30;
/// TODO
......@@ -180,12 +181,211 @@ bitflags! {
}
}
// `sigprocmask` actions
/// Block the signal
pub const SIG_BLOCK: usize = 0;
/// Unblock the signal
pub const SIG_UNBLOCK: usize = 1;
/// Set the signal mask
pub const SIG_SETMASK: usize = 2;
bitflags! {
/// The mask of blocked signals
pub struct SigMask: usize {
#[allow(missing_docs)]
const FOO = 42;
// TODO
const SIGHUP = 1 << 0;
#[allow(missing_docs)]
const SIGINT = 1 << 1;
#[allow(missing_docs)]
const SIGQUIT = 1 << 2;
#[allow(missing_docs)]
const SIGILL = 1 << 3;
#[allow(missing_docs)]
const SIGTRAP = 1 << 4;
#[allow(missing_docs)]
const SIGABRT = 1 << 5;
#[allow(missing_docs)]
const SIGBUS = 1 << 6;
#[allow(missing_docs)]
const SIGFPE = 1 << 7;
#[allow(missing_docs)]
const SIGKILL = 1 << 8;
#[allow(missing_docs)]
const SIGUSR1 = 1 << 9;
#[allow(missing_docs)]
const SIGSEGV = 1 << 10;
#[allow(missing_docs)]
const SIGUSR2 = 1 << 11;
#[allow(missing_docs)]
const SIGPIPE = 1 << 12;
#[allow(missing_docs)]
const SIGALRM = 1 << 13;
#[allow(missing_docs)]
const SIGTERM = 1 << 14;
#[allow(missing_docs)]
const SIGSTKFLT = 1 << 15;
#[allow(missing_docs)]
const SIGCHLD = 1 << 16;
#[allow(missing_docs)]
const SIGCONT = 1 << 17;
#[allow(missing_docs)]
const SIGSTOP = 1 << 18;
#[allow(missing_docs)]
const SIGTSTP = 1 << 19;
#[allow(missing_docs)]
const SIGTTIN = 1 << 20;
#[allow(missing_docs)]
const SIGTTOUT = 1 << 21;
#[allow(missing_docs)]
const SIGURG = 1 << 22;
#[allow(missing_docs)]
const SIGXCPU = 1 << 23;
#[allow(missing_docs)]
const SIGXFSZ = 1 << 24;
#[allow(missing_docs)]
const SIGVTALRM = 1 << 25;
#[allow(missing_docs)]
const SIGPROF = 1 << 26;
#[allow(missing_docs)]
const SIGWINCH = 1 << 27;
#[allow(missing_docs)]
const SIGIO = 1 << 28;
#[allow(missing_docs)]
const SIGPWR = 1 << 29;
#[allow(missing_docs)]
const SIGSYS = 1 << 30;
#[allow(missing_docs)]
const SIGRTMIN = 1 << 31;
#[allow(missing_docs)]
const SIGRT_1 = 1 << 32;
#[allow(missing_docs)]
const SIGRT_2 = 1 << 33;
#[allow(missing_docs)]
const SIGRT_3 = 1 << 34;
#[allow(missing_docs)]
const SIGRT_4 = 1 << 35;
#[allow(missing_docs)]
const SIGRT_5 = 1 << 36;
#[allow(missing_docs)]
const SIGRT_6 = 1 << 37;
#[allow(missing_docs)]
const SIGRT_7 = 1 << 38;
#[allow(missing_docs)]
const SIGRT_8 = 1 << 39;
#[allow(missing_docs)]
const SIGRT_9 = 1 << 40;
#[allow(missing_docs)]
const SIGRT_10 = 1 << 41;
#[allow(missing_docs)]
const SIGRT_11 = 1 << 42;
#[allow(missing_docs)]
const SIGRT_12 = 1 << 43;
#[allow(missing_docs)]
const SIGRT_13 = 1 << 44;
#[allow(missing_docs)]
const SIGRT_14 = 1 << 45;
#[allow(missing_docs)]
const SIGRT_15 = 1 << 46;
#[allow(missing_docs)]
const SIGRT_16 = 1 << 47;
#[allow(missing_docs)]
const SIGRT_17 = 1 << 48;
#[allow(missing_docs)]
const SIGRT_18 = 1 << 49;
#[allow(missing_docs)]
const SIGRT_19 = 1 << 50;
#[allow(missing_docs)]
const SIGRT_20 = 1 << 51;
#[allow(missing_docs)]
const SIGRT_21 = 1 << 52;
#[allow(missing_docs)]
const SIGRT_22 = 1 << 53;
#[allow(missing_docs)]
const SIGRT_23 = 1 << 54;
#[allow(missing_docs)]
const SIGRT_24 = 1 << 55;
#[allow(missing_docs)]
const SIGRT_25 = 1 << 56;
#[allow(missing_docs)]
const SIGRT_26 = 1 << 57;
#[allow(missing_docs)]
const SIGRT_27 = 1 << 58;
#[allow(missing_docs)]
const SIGRT_28 = 1 << 59;
#[allow(missing_docs)]
const SIGRT_29 = 1 << 60;
#[allow(missing_docs)]
const SIGRT_30 = 1 << 61;
#[allow(missing_docs)]
const SIGRT_31 = 1 << 62;
#[allow(missing_docs)]
const SIGRT_32 = 1 << 63;
}
}
......@@ -375,6 +575,14 @@ impl From<usize> for Signal {
}
}
impl From<Signal> for SigMask {
fn from(val: Signal) -> Self {
use core::mem::transmute;
unsafe { transmute::<usize, Self>(1 << (val as usize - 1)) }
}
}
impl fmt::Debug for SigAction {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{{sa_handler={:#x}, sa_mask={:?}, sa_flags={:?}, sa_restorer={:#x}}}",
......@@ -423,9 +631,13 @@ pub fn send_signal(sig: Signal, info: SigInfo) -> Result<(), NoneError> {
/// Helper functions to send a signal to a specific process
pub fn send_signal_to(pid: Pid, sig: Signal, info: SigInfo) -> Result<(), NoneError> {
let mut processes = PROCESSES.write();
processes.get_mut(&pid)?.signals.push_back(
(sig, info)
);
let process = processes.get_mut(&pid)?;
if !process.signal_mask.contains(SigMask::from(sig)) {
process.signals.push_back(
(sig, info)
);
}
Ok(())
}
......@@ -67,6 +67,8 @@ pub struct Thread {
/// The save of the SSE state
pub fx: u64,
// TODO: Signal mask?
}
impl Thread {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment