diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index 0db1ed47..5cfe5cc5 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -35,7 +35,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_sigaction(args[0] as u32, args[1] as *const SignalAction, args[2] as *mut SignalAction), + SYSCALL_SIGACTION => sys_sigaction(args[0], args[1] as *const SignalAction, args[2] as *mut SignalAction), SYSCALL_SIGPROCMASK => sys_sigprocmask(args[0] as u32), SYSCALL_SIGRETURN => sys_sigretrun(), SYSCALL_GET_TIME => sys_get_time(), diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index 351f7df1..ed6e1551 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, SignalAction, + suspend_current_and_run_next, SignalFlags, SignalAction, MAX_SIG, }; use crate::timer::get_time_ms; use alloc::string::String; @@ -159,15 +159,18 @@ fn check_sigaction_error(signal: SignalFlags, action: usize, old_action: usize) } } -pub fn sys_sigaction(signal: u32, action: *const SignalAction, old_action: *mut SignalAction) -> isize { +pub fn sys_sigaction(signum: usize, 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 signum as usize > MAX_SIG { + return -1; + } + if let Some(flag) = SignalFlags::from_bits(1 << signum) { 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]; + let old_kernel_action = inner.signal_actions.table[signum]; if old_kernel_action.mask != SignalFlags::from_bits(40).unwrap() { *translated_refmut(token, old_action) = old_kernel_action; } else { @@ -175,7 +178,7 @@ pub fn sys_sigaction(signal: u32, action: *const SignalAction, old_action: *mut ref_old_action.handler = old_kernel_action.handler; } let ref_action = translated_ref(token, action); - inner.signal_actions.table[signal as usize] = *ref_action; + inner.signal_actions.table[signum] = *ref_action; return 0; } } diff --git a/user/src/bin/sig_tests.rs b/user/src/bin/sig_tests.rs new file mode 100644 index 00000000..7f566dc0 --- /dev/null +++ b/user/src/bin/sig_tests.rs @@ -0,0 +1,158 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{sigaction, sigprocmask, SignalAction, SignalFlags, fork, exit, wait, kill, getpid, sleep}; + +fn func() { + println!("user_sig_test succsess"); +} + +fn user_sig_test_failsignum() { + let mut new = SignalAction::default(); + let old = SignalAction::default(); + new.handler = func as usize; + if sigaction(50, &new, &old) >= 0 { + panic!("Wrong sigaction but success!"); + } +} + +fn user_sig_test_kill() { + let mut new = SignalAction::default(); + let old = SignalAction::default(); + new.handler = func as usize; + + if sigaction(10, &new, &old) < 0 { + panic!("Sigaction failed!"); + } + if kill(getpid() as usize, 1 << 10) < 0 { + println!("Kill failed!"); + exit(1); + } +} + +fn user_sig_test_multiprocsignals() { + let pid= fork(); + if pid == 0{ + let mut new = SignalAction::default(); + let old = SignalAction::default(); + new.handler = func as usize; + if sigaction(10, &new, &old) < 0 { + panic!("Sigaction failed!"); + } + } else { + if kill(pid as usize, 1 << 10) < 0 { + println!("Kill failed!"); + exit(1); + } + let mut exit_code = 0; + wait(&mut exit_code); + } +} + +fn user_sig_test_restore() { + let mut new = SignalAction::default(); + let old = SignalAction::default(); + let old2 = SignalAction::default(); + new.handler = func as usize; + + if sigaction(10, &new, &old) < 0 { + panic!("Sigaction failed!"); + } + + if sigaction(10, &old, &old2) < 0 { + panic!("Sigaction failed!"); + } + + if old2.handler != new.handler { + println!("Restore failed!"); + exit(-1); + } +} + +fn kernel_sig_test_ignore() { + sigprocmask(SignalFlags::SIGSTOP.bits() as u32); + if kill(getpid() as usize, SignalFlags::SIGSTOP.bits()) < 0{ + println!("kill faild\n"); + exit(-1); + } +} + +fn kernel_sig_test_stop_cont() { + let pid= fork(); + if pid == 0 { + kill(getpid() as usize, SignalFlags::SIGSTOP.bits()); + sleep(1000); + exit(-1); + } else { + sleep(5000); + kill(pid as usize, SignalFlags::SIGCONT.bits()); + let mut exit_code = 0; + wait(&mut exit_code); + } +} + +fn kernel_sig_test_failignorekill() { + let mut new = SignalAction::default(); + let old = SignalAction::default(); + new.handler = func as usize; + + if sigaction(9, &new, &old) >= 0 { + panic!("Should not set sigaction to kill!"); + } + + if sigaction(9, &new, 0 as *const SignalAction) >= 0 { + panic!("Should not set sigaction to kill!"); + } + + if sigaction(9, 0 as *const SignalAction, &old) >= 0 { + panic!("Should not set sigaction to kill!"); + } +} + + +fn run(f: fn()) -> bool { + let pid = fork(); + if pid == 0 { + f(); + exit(0); + } else { + let mut exit_code: i32 = 0; + wait(&mut exit_code); + if exit_code != 0 { + println!("FAILED!"); + } else { + println!("OK!"); + } + exit_code == 0 + } +} + +#[no_mangle] +pub fn main() -> i32 { + let tests: [(fn(), &str); 7] = [ + (user_sig_test_failsignum, "user_sig_test_failsignum"), + (user_sig_test_kill, "user_sig_test_kill"), + (user_sig_test_multiprocsignals, "user_sig_test_multiprocsignals"), + (user_sig_test_restore, "user_sig_test_restore"), + (kernel_sig_test_ignore, "kernel_sig_test_ignore"), + (kernel_sig_test_stop_cont, "kernel_sig_test_stop_cont"), + (kernel_sig_test_failignorekill, "kernel_sig_test_failignorekill") + ]; + let mut fail_num = 0; + for test in tests { + println!("Testing {}", test.1); + if !run(test.0) { + fail_num += 1; + } + } + if fail_num == 0 { + println!("ALL TESTS PASSED"); + 0 + } else { + println!("SOME TESTS FAILED"); + -1 + } +} diff --git a/user/src/lib.rs b/user/src/lib.rs index f15d9ce7..a17fbcc3 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -139,16 +139,68 @@ pub fn sleep(period_ms: usize) { } } +/// 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::empty() + } + } +} + bitflags! { pub struct SignalFlags: i32 { - const SIGINT = 1 << 2; - const SIGILL = 1 << 4; - const SIGABRT = 1 << 6; - const SIGFPE = 1 << 8; - const SIGSEGV = 1 << 11; + const SIGDEF = 1; // Default signal handling + const SIGHUP = 1 << 1; + const SIGINT = 1 << 2; + const SIGQUIT = 1 << 3; + const SIGILL = 1 << 4; + const SIGTRAP = 1 << 5; + const SIGABRT = 1 << 6; + const SIGBUS = 1 << 7; + const SIGFPE = 1 << 8; + const SIGKILL = 1 << 9; + const SIGUSR1 = 1 << 10; + const SIGSEGV = 1 << 11; + const SIGUSR2 = 1 << 12; + const SIGPIPE = 1 << 13; + const SIGALRM = 1 << 14; + const SIGTERM = 1 << 15; + const SIGSTKFLT = 1 << 16; + const SIGCHLD = 1 << 17; + const SIGCONT = 1 << 18; + const SIGSTOP = 1 << 19; + const SIGTSTP = 1 << 20; + const SIGTTIN = 1 << 21; + const SIGTTOU = 1 << 22; + const SIGURG = 1 << 23; + const SIGXCPU = 1 << 24; + const SIGXFSZ = 1 << 25; + const SIGVTALRM = 1 << 26; + const SIGPROF = 1 << 27; + const SIGWINCH = 1 << 28; + const SIGIO = 1 << 29; + const SIGPWR = 1 << 30; + const SIGSYS = 1 << 31; } } pub fn kill(pid: usize, signal: i32) -> isize { sys_kill(pid, signal) } + +pub fn sigaction(signum: usize, action: *const SignalAction, old_action: *const SignalAction) -> isize { + sys_sigaction(signum, action, old_action) +} + +pub fn sigprocmask(mask: u32) -> isize { + sys_sigprocmask(mask) +} diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 1481de68..ea5c2014 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -1,5 +1,7 @@ use core::arch::asm; +use crate::SignalAction; + const SYSCALL_DUP: usize = 24; const SYSCALL_OPEN: usize = 56; const SYSCALL_CLOSE: usize = 57; @@ -9,6 +11,8 @@ const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; const SYSCALL_KILL: usize = 129; +const SYSCALL_SIGACTION: usize = 134; +const SYSCALL_SIGPROCMASK: usize = 135; const SYSCALL_GET_TIME: usize = 169; const SYSCALL_GETPID: usize = 172; const SYSCALL_FORK: usize = 220; @@ -91,3 +95,11 @@ pub fn sys_exec(path: &str, args: &[*const u8]) -> isize { pub fn sys_waitpid(pid: isize, exit_code: *mut i32) -> isize { syscall(SYSCALL_WAITPID, [pid as usize, exit_code as usize, 0]) } + +pub fn sys_sigaction(signum: usize, action: *const SignalAction, old_action: *const SignalAction) -> isize { + syscall(SYSCALL_SIGACTION, [signum, action as usize, old_action as usize]) +} + +pub fn sys_sigprocmask(mask: u32) -> isize { + syscall(SYSCALL_SIGPROCMASK, [mask as usize, 0, 0]) +}