From 0e8e1b5c4ef9d174458dd9a0d3d27cd113d10c4a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 5 Jul 2017 21:45:53 -0600 Subject: [PATCH] WIP: Signal handling --- Cargo.toml | 2 +- src/context/context.rs | 7 +++++-- src/context/switch.rs | 20 ++++++++++++++++---- src/scheme/env.rs | 2 +- src/syscall/mod.rs | 1 + src/syscall/process.rs | 30 +++++++++++++++++++++++++++++- 6 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 746c704aa5..dd5428500c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ alloc_kernel = { path = "alloc_kernel" } bitflags = "0.7" spin = "0.4" raw-cpuid = { git = "https://github.com/gz/rust-cpuid", branch = "master" } -redox_syscall = "0.1" +redox_syscall = { version = "0.1", path = "../syscall" } [dependencies.goblin] version = "0.0.10" diff --git a/src/context/context.rs b/src/context/context.rs index b50773d4c9..f35a5d02e3 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -82,7 +82,9 @@ pub struct Context { /// The process environment pub env: Arc, Arc>>>>>, /// The open files in the scheme - pub files: Arc>>> + pub files: Arc>>>, + /// Singal handlers + pub handlers: Arc>>, } impl Context { @@ -115,7 +117,8 @@ impl Context { cwd: Arc::new(Mutex::new(Vec::new())), events: Arc::new(WaitQueue::new()), env: Arc::new(Mutex::new(BTreeMap::new())), - files: Arc::new(Mutex::new(Vec::new())) + files: Arc::new(Mutex::new(Vec::new())), + handlers: Arc::new(Mutex::new(BTreeMap::new())), } } diff --git a/src/context/switch.rs b/src/context/switch.rs index 4413d89347..fd560c9331 100644 --- a/src/context/switch.rs +++ b/src/context/switch.rs @@ -109,7 +109,6 @@ pub unsafe fn switch() -> bool { arch::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst); if let Some(sig) = to_sig { - println!("Handle {}", sig); (&mut *to_ptr).arch.signal_stack(signal_handler, sig); } @@ -118,7 +117,20 @@ pub unsafe fn switch() -> bool { true } -extern "C" fn signal_handler(signal: usize) { - println!("Signal handler: {}", signal); - syscall::exit(signal); +extern "C" fn signal_handler(sig: usize) { + let handler = { + let contexts = contexts(); + let context_lock = contexts.current().expect("context::signal_handler not inside of context"); + let context = context_lock.read(); + let handlers = context.handlers.lock(); + handlers.get(&(sig as u8)).map_or(0, |sig| *sig) + }; + + println!("Signal handler: {}, {:X}", sig, handler); + + if handler == 0 { + syscall::exit(sig); + } else { + // TODO: Call handler + } } diff --git a/src/scheme/env.rs b/src/scheme/env.rs index 062658cca5..112d896ccb 100644 --- a/src/scheme/env.rs +++ b/src/scheme/env.rs @@ -214,7 +214,7 @@ impl Scheme for EnvScheme { self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) } - fn unlink(&self, path: &[u8], uid: u32, _gid: u32) -> Result { + fn unlink(&self, path: &[u8], _uid: u32, _gid: u32) -> Result { let env_lock = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 5e9d59a50a..f2d69b45c7 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -80,6 +80,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_EXIT => exit((b & 0xFF) << 8), SYS_KILL => kill(ContextId::from(b), c), SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into), + SYS_SIGNAL => signal(b, c), SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), SYS_IOPL => iopl(b, stack), diff --git a/src/syscall/process.rs b/src/syscall/process.rs index d32adec0b2..5db228f4b8 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -18,7 +18,7 @@ use scheme::{self, FileHandle}; use syscall; use syscall::data::Stat; use syscall::error::*; -use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, O_CLOEXEC, WNOHANG}; +use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, O_CLOEXEC, SIG_DFL, WNOHANG}; use syscall::validate::{validate_slice, validate_slice_mut}; pub fn brk(address: usize) -> Result { @@ -83,6 +83,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let cwd; let env; let files; + let handlers; // Copy from old process { @@ -247,6 +248,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { } else { files = Arc::new(Mutex::new(context.files.lock().clone())); } + + if flags & CLONE_SIGHAND == CLONE_SIGHAND { + handlers = context.handlers.clone(); + } else { + handlers = Arc::new(Mutex::new(context.handlers.lock().clone())); + } } // If not cloning files, dup to get a new number from scheme @@ -445,6 +452,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { context.env = env; context.files = files; + + context.handlers = handlers; } } @@ -726,6 +735,8 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { let files = Arc::new(Mutex::new(context.files.lock().clone())); context.files = files.clone(); + context.handlers = Arc::new(Mutex::new(BTreeMap::new())); + let vfork = context.vfork; context.vfork = false; (vfork, context.ppid, files) @@ -958,6 +969,23 @@ pub fn kill(pid: ContextId, sig: usize) -> Result { } } +pub fn signal(sig: usize, handler: usize) -> Result { + if sig > 0 && sig <= 0x7F { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + let mut handlers = context.handlers.lock(); + let previous = if handler == SIG_DFL { + handlers.remove(&(sig as u8)) + } else { + handlers.insert(sig as u8, handler) + }; + Ok(previous.unwrap_or(0)) + } else { + Err(Error::new(EINVAL)) + } +} + fn reap(pid: ContextId) -> Result { // Spin until not running let mut running = true;