diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index e7d7aae0..c3953ff8 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -21,6 +21,8 @@ mod process; use fs::*; use process::*; +use crate::task::SignalAction; + pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { SYSCALL_DUP => sys_dup(args[0]), @@ -32,7 +34,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_YIELD => sys_yield(), SYSCALL_KILL => sys_kill(args[0], args[1] as u32), - SYSCALL_SIGACTION => sys_sigation(args[0] as u32, args[1], args[2]), + SYSCALL_SIGACTION => sys_sigaction(args[0] as u32, args[1] as *const SignalAction, args[2] as *mut SignalAction), SYSCALL_SIGPROCMASK => sys_sigprocmask(args[0] as u32), SYSCALL_GET_TIME => sys_get_time(), SYSCALL_GETPID => sys_getpid(), diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index aa591785..39ac8b8b 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -2,7 +2,7 @@ use crate::fs::{open_file, OpenFlags}; use crate::mm::{translated_ref, translated_refmut, translated_str}; use crate::task::{ add_task, current_task, current_user_token, exit_current_and_run_next, pid2task, - suspend_current_and_run_next, SignalFlags, + suspend_current_and_run_next, SignalFlags, SignalAction, }; use crate::timer::get_time_ms; use alloc::string::String; @@ -109,10 +109,10 @@ pub fn sys_kill(pid: usize, signal: u32) -> isize { if let Some(flag) = SignalFlags::from_bits(signal) { // insert the signal if legal let mut task_ref = task.inner_exclusive_access(); - if task_ref.pending_signals.contains(flag) { + if task_ref.signals.contains(flag) { return -1; } - task_ref.pending_signals.insert(flag); + task_ref.signals.insert(flag); 0 } else { -1 @@ -137,6 +137,34 @@ pub fn sys_sigprocmask(mask: u32) -> isize { } } -pub fn sys_sigation(_signal: u32, _action: usize, _old_action: usize) -> isize { - 0 +fn check_sigaction_error(signal: SignalFlags, action: usize, old_action: usize) -> bool { + if action == 0 || old_action == 0 || signal == SignalFlags::SIGKILL || + signal == SignalFlags::SIGSTOP { + true + } else { + false + } +} + +pub fn sys_sigaction(signal: u32, action: *const SignalAction, old_action: *mut SignalAction) -> isize { + let token = current_user_token(); + if let Some(task) = current_task() { + let mut inner = task.inner_exclusive_access(); + if let Some(flag) = SignalFlags::from_bits(signal) { + if check_sigaction_error(flag, action as usize, old_action as usize) { + return -1; + } + let old_kernel_action = inner.signal_actions.table[signal as usize]; + if old_kernel_action.mask != SignalFlags::from_bits(40).unwrap() { + *translated_refmut(token, old_action) = old_kernel_action; + } else { + let mut ref_old_action = *translated_refmut(token, old_action); + ref_old_action.handler = old_kernel_action.handler; + } + let ref_action = translated_ref(token, action); + inner.signal_actions.table[signal as usize] = *ref_action; + return 0; + } + } + -1 } diff --git a/os/src/task/action.rs b/os/src/task/action.rs new file mode 100644 index 00000000..a891ab75 --- /dev/null +++ b/os/src/task/action.rs @@ -0,0 +1,32 @@ +use crate::task::{SignalFlags, MAX_SIG}; + + +/// Action for a signal +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct SignalAction { + pub handler: usize, + pub mask: SignalFlags +} + +impl Default for SignalAction { + fn default() -> Self { + Self { + handler: 0, + mask: SignalFlags::from_bits(40).unwrap() + } + } +} + +#[derive(Clone)] +pub struct SignalActions { + pub table: [SignalAction; MAX_SIG + 1], +} + +impl Default for SignalActions { + fn default() -> Self { + Self { + table: [SignalAction::default(); MAX_SIG + 1], + } + } +} diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 443ee01e..2bc3ae86 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -4,6 +4,7 @@ mod pid; mod processor; mod signal; mod switch; +mod action; #[allow(clippy::module_inception)] mod task; @@ -21,7 +22,8 @@ pub use pid::{pid_alloc, KernelStack, PidHandle}; pub use processor::{ current_task, current_trap_cx, current_user_token, run_tasks, schedule, take_current_task, }; -pub use signal::SignalFlags; +pub use signal::{SignalFlags, MAX_SIG}; +pub use action::{SignalAction, SignalActions}; pub fn suspend_current_and_run_next() { // There must be an application running. diff --git a/os/src/task/signal.rs b/os/src/task/signal.rs index d646c19f..009ec583 100644 --- a/os/src/task/signal.rs +++ b/os/src/task/signal.rs @@ -1,5 +1,7 @@ use bitflags::*; +pub const MAX_SIG: usize = 31; + bitflags! { pub struct SignalFlags: u32 { const SIGHUP = 1 << 1; diff --git a/os/src/task/task.rs b/os/src/task/task.rs index 6db89537..9d7a18c4 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -1,4 +1,4 @@ -use super::TaskContext; +use super::{TaskContext, SignalActions}; use super::{pid_alloc, KernelStack, PidHandle, SignalFlags}; use crate::config::TRAP_CONTEXT; use crate::fs::{File, Stdin, Stdout}; @@ -30,8 +30,11 @@ pub struct TaskControlBlockInner { pub exit_code: i32, pub fd_table: Vec>>, pub signals: SignalFlags, - pub pending_signals: SignalFlags, - pub signal_mask: SignalFlags + pub signal_mask: SignalFlags, + // if a the task is handling a signal + pub handling_flag: bool, + // Signal actions + pub signal_actions: SignalActions } impl TaskControlBlockInner { @@ -94,8 +97,9 @@ impl TaskControlBlock { Some(Arc::new(Stdout)), ], signals: SignalFlags::empty(), - pending_signals: SignalFlags::empty(), - signal_mask: SignalFlags::empty() + signal_mask: SignalFlags::empty(), + handling_flag: false, + signal_actions: SignalActions::default() }) }, }; @@ -198,8 +202,10 @@ impl TaskControlBlock { exit_code: 0, fd_table: new_fd_table, signals: SignalFlags::empty(), - pending_signals: SignalFlags::empty(), - signal_mask: SignalFlags::empty() + // inherit the signal_mask and signal_action + signal_mask: parent_inner.signal_mask, + handling_flag: false, + signal_actions: parent_inner.signal_actions.clone() }) }, });