From 49d5c3392835070ae295a1ef1bb46337d9da1ad3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 3 Jan 2018 22:34:50 -0700 Subject: [PATCH] Add support for WCONTINUED and WUNTRACED Fix issues with SIGCONT --- Cargo.lock | 56 ++++++++++++------------ src/context/mod.rs | 3 ++ src/context/signal.rs | 96 ++++++++++++++++++++++++++++++++++++++++++ src/context/switch.rs | 66 +---------------------------- src/syscall/process.rs | 96 +++++++++++++++++++++++++++--------------- syscall | 2 +- 6 files changed, 192 insertions(+), 127 deletions(-) create mode 100644 src/context/signal.rs diff --git a/Cargo.lock b/Cargo.lock index af923d3..564c1f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,9 @@ name = "cargo_metadata" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -46,7 +46,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.177 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -60,10 +60,10 @@ dependencies = [ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -135,7 +135,7 @@ dependencies = [ "clippy 0.0.177 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.33", + "redox_syscall 0.1.35", "spin 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -147,7 +147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -168,7 +168,7 @@ name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -224,23 +224,23 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.33" +version = "0.1.35" [[package]] name = "regex" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -263,22 +263,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -287,13 +287,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -333,7 +333,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -408,7 +408,7 @@ dependencies = [ "checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" +"checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb" "checksum linked_list_allocator 0.4.1 (git+https://github.com/redox-os/linked-list-allocator.git)" = "" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" @@ -420,15 +420,15 @@ dependencies = [ "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" "checksum raw-cpuid 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779585861d55e586db9d6abe4352cd9466e09a3319342c417baf34b2740af74e" -"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum scroll 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d916a75d18d4c559fa7312afe6f522fe5b63176e6591d02ed81017c22f8ea27" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "386122ba68c214599c44587e0c0b411e8d90894503a95425b4f9508e4317901f" -"checksum serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0bfa6c5784e7d110514448da0e1dbad41ea5514c3e68be755b23858b83a399" -"checksum serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "730fe9f29fe8db69a601837f416e46cba07792031ed6b27557a43e49d62d89ae" -"checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" +"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" +"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" "checksum spin 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4deb3c2455c73779e6d3eebceae9599fc70957e54c69fe88f93aa48e62f432" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" diff --git a/src/context/mod.rs b/src/context/mod.rs index d573087..dc4ef3f 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -30,6 +30,9 @@ pub mod file; /// Memory struct - contains a set of pages for a context pub mod memory; +/// Signal handling +pub mod signal; + /// Timeout handling pub mod timeout; diff --git a/src/context/signal.rs b/src/context/signal.rs new file mode 100644 index 0000000..d2d9043 --- /dev/null +++ b/src/context/signal.rs @@ -0,0 +1,96 @@ +use alloc::arc::Arc; +use core::mem; + +use context::{contexts, Status}; +use start::usermode; +use syscall; +use syscall::flag::{SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU}; + +pub extern "C" fn signal_handler(sig: usize) { + let (action, restorer) = { + let contexts = contexts(); + let context_lock = contexts.current().expect("context::signal_handler not inside of context"); + let context = context_lock.read(); + let actions = context.actions.lock(); + actions[sig] + }; + + let handler = action.sa_handler as usize; + println!("Handler {}: {:X}", sig, handler); + if handler == SIG_DFL { + match sig { + SIGCHLD => { + println!("SIGCHLD"); + }, + SIGCONT => { + println!("Continue"); + + { + let contexts = contexts(); + + let (pid, ppid) = { + let context_lock = contexts.current().expect("context::signal_handler not inside of context"); + let mut context = context_lock.write(); + context.status = Status::Runnable; + (context.id, context.ppid) + }; + + if let Some(parent_lock) = contexts.get(ppid) { + let waitpid = { + let mut parent = parent_lock.write(); + Arc::clone(&parent.waitpid) + }; + + waitpid.send(pid, 0xFFFF); + } else { + println!("{}: {} not found for continue", pid.into(), ppid.into()); + } + } + }, + SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => { + println!("Stop {}", sig); + + { + let contexts = contexts(); + + let (pid, ppid) = { + let context_lock = contexts.current().expect("context::signal_handler not inside of context"); + let mut context = context_lock.write(); + context.status = Status::Stopped(sig); + (context.id, context.ppid) + }; + + if let Some(parent_lock) = contexts.get(ppid) { + let waitpid = { + let mut parent = parent_lock.write(); + Arc::clone(&parent.waitpid) + }; + + waitpid.send(pid, (sig << 8) | 0x7F); + } else { + println!("{}: {} not found for stop", pid.into(), ppid.into()); + } + } + }, + _ => { + println!("Exit {}", sig); + syscall::exit(sig); + } + } + } else if handler == SIG_IGN { + println!("Ignore"); + } else { + println!("Call {:X}", handler); + + unsafe { + let mut sp = ::USER_SIGSTACK_OFFSET + ::USER_SIGSTACK_SIZE - 256; + + sp = (sp / 16) * 16; + + sp -= mem::size_of::(); + *(sp as *mut usize) = restorer; + + usermode(handler, sp, sig); + } + } +} diff --git a/src/context/switch.rs b/src/context/switch.rs index e3d0ea7..3e0c947 100644 --- a/src/context/switch.rs +++ b/src/context/switch.rs @@ -1,13 +1,10 @@ -use core::mem; use core::sync::atomic::Ordering; -use context::{arch, contexts, Context, Status, CONTEXT_ID}; -use start::usermode; -use syscall::flag::{SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU}; +use context::{arch, contexts, Context, Status, CONTEXT_ID}; +use context::signal::signal_handler; use gdt; use interrupt; use interrupt::irq::PIT_TICKS; -use syscall; use time; /// Switch to the next context @@ -152,62 +149,3 @@ pub unsafe fn switch() -> bool { true } } - -extern "C" fn signal_handler(sig: usize) { - let (action, restorer) = { - let contexts = contexts(); - let context_lock = contexts.current().expect("context::signal_handler not inside of context"); - let context = context_lock.read(); - let actions = context.actions.lock(); - actions[sig] - }; - - let handler = action.sa_handler as usize; - println!("Handler {}: {:X}", sig, handler); - if handler == SIG_DFL { - match sig { - SIGCHLD => { - println!("SIGCHLD"); - }, - SIGCONT => { - println!("Continue"); - - { - let contexts = contexts(); - let context_lock = contexts.current().expect("context::signal_handler not inside of context"); - let mut context = context_lock.write(); - context.status = Status::Runnable; - } - }, - SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => { - println!("Stop {}", sig); - - { - let contexts = contexts(); - let context_lock = contexts.current().expect("context::signal_handler not inside of context"); - let mut context = context_lock.write(); - context.status = Status::Stopped(sig); - } - }, - _ => { - println!("Exit {}", sig); - syscall::exit(sig); - } - } - } else if handler == SIG_IGN { - println!("Ignore"); - } else { - println!("Call {:X}", handler); - - unsafe { - let mut sp = ::USER_SIGSTACK_OFFSET + ::USER_SIGSTACK_SIZE - 256; - - sp = (sp / 16) * 16; - - sp -= mem::size_of::(); - *(sp as *mut usize) = restorer; - - usermode(handler, sp, sig); - } - } -} diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 8d13c7b..62672bc 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -22,7 +22,7 @@ use scheme::FileHandle; use syscall; use syscall::data::{SigAction, Stat}; use syscall::error::*; -use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, SIG_DFL, SIGTERM, WNOHANG}; +use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, SIG_DFL, SIGCONT, SIGTERM, WCONTINUED, WNOHANG, WUNTRACED}; use syscall::validate::{validate_slice, validate_slice_mut}; pub fn brk(address: usize) -> Result { @@ -974,7 +974,7 @@ pub fn kill(pid: ContextId, sig: usize) -> Result { (context.ruid, context.euid, context.pgid) }; - if sig > 0 && sig <= 0x7F { + if sig > 0 && sig < 0x7F { let mut found = 0; let mut sent = 0; @@ -986,6 +986,12 @@ pub fn kill(pid: ContextId, sig: usize) -> Result { || euid == context.ruid || ruid == context.ruid { + // Convert stopped processes to blocked if sending SIGCONT + if sig == SIGCONT { + if let context::Status::Stopped(_sig) = context.status { + context.status = context::Status::Blocked; + } + } context.pending.push_back(sig as u8); true } else { @@ -1158,47 +1164,69 @@ pub fn waitpid(pid: ContextId, status_ptr: usize, flags: usize) -> Result Option> { + if status == 0xFFFF { + if flags & WCONTINUED == WCONTINUED { status_slice[0] = status; - reap(w_pid) + Some(Ok(w_pid)) } else { - Ok(ContextId::from(0)) + None + } + } else if status & 0xFF == 0x7F { + if flags & WUNTRACED == WUNTRACED { + status_slice[0] = status; + Some(Ok(w_pid)) + } else { + None } } else { - let (w_pid, status) = waitpid.receive_any(); status_slice[0] = status; - reap(w_pid) + Some(reap(w_pid)) } - } else { - let status = { - let contexts = context::contexts(); - let context_lock = contexts.get(pid).ok_or(Error::new(ECHILD))?; - let mut context = context_lock.write(); - if context.ppid != ppid { - println!("Hack for rustc - changing ppid of {} from {} to {}", context.id.into(), context.ppid.into(), ppid.into()); - context.ppid = ppid; - //return Err(Error::new(ECHILD)); + }; + + loop { + let res_opt = if pid.into() == 0 { + if flags & WNOHANG == WNOHANG { + if let Some((w_pid, status)) = waitpid.receive_any_nonblock() { + grim_reaper(w_pid, status) + } else { + Some(Ok(ContextId::from(0))) + } + } else { + let (w_pid, status) = waitpid.receive_any(); + grim_reaper(w_pid, status) + } + } else { + let status = { + let contexts = context::contexts(); + let context_lock = contexts.get(pid).ok_or(Error::new(ECHILD))?; + let mut context = context_lock.write(); + if context.ppid != ppid { + println!("Hack for rustc - changing ppid of {} from {} to {}", context.id.into(), context.ppid.into(), ppid.into()); + context.ppid = ppid; + //return Err(Error::new(ECHILD)); + } + context.status + }; + + if let context::Status::Exited(status) = status { + let _ = waitpid.receive_nonblock(&pid); + grim_reaper(pid, status) + } else if flags & WNOHANG == WNOHANG { + if let Some(status) = waitpid.receive_nonblock(&pid) { + grim_reaper(pid, status) + } else { + Some(Ok(ContextId::from(0))) + } + } else { + let status = waitpid.receive(&pid); + grim_reaper(pid, status) } - context.status }; - if let context::Status::Exited(status) = status { - let _ = waitpid.receive_nonblock(&pid); - status_slice[0] = status; - reap(pid) - } else if flags & WNOHANG == WNOHANG { - if let Some(status) = waitpid.receive_nonblock(&pid) { - status_slice[0] = status; - reap(pid) - } else { - Ok(ContextId::from(0)) - } - } else { - let status = waitpid.receive(&pid); - status_slice[0] = status; - reap(pid) + if let Some(res) = res_opt { + return res; } } } diff --git a/syscall b/syscall index 414b8e0..8f01290 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 414b8e0be011c70d5c55692f4dd835184f33579f +Subproject commit 8f012900589854cd54ac0a6edb9a3f2b0e017669