diff --git a/Cargo.lock b/Cargo.lock index 564c1f6..f35f179 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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.35", + "redox_syscall 0.1.37", "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)", ] @@ -224,7 +224,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.35" +version = "0.1.37" [[package]] name = "regex" diff --git a/src/context/context.rs b/src/context/context.rs index 1ef168f..f9c01ea 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -1,6 +1,7 @@ use alloc::arc::Arc; use alloc::boxed::Box; use alloc::{BTreeMap, Vec, VecDeque}; +use core::cmp::Ordering; use core::mem; use spin::Mutex; @@ -27,6 +28,65 @@ pub enum Status { Exited(usize) } +#[derive(Copy, Clone, Debug)] +pub struct WaitpidKey { + pub pid: Option, + pub pgid: Option, +} + +impl Ord for WaitpidKey { + fn cmp(&self, other: &WaitpidKey) -> Ordering { + // If both have pid set, compare that + if let Some(s_pid) = self.pid { + if let Some(o_pid) = other.pid { + return s_pid.cmp(&o_pid); + } + } + + // If both have pgid set, compare that + if let Some(s_pgid) = self.pgid { + if let Some(o_pgid) = other.pgid { + return s_pgid.cmp(&o_pgid); + } + } + + // If either has pid set, it is greater + if self.pid.is_some() { + return Ordering::Greater; + } + + if other.pid.is_some() { + return Ordering::Less; + } + + // If either has pgid set, it is greater + if self.pgid.is_some() { + return Ordering::Greater; + } + + if other.pgid.is_some() { + return Ordering::Less; + } + + // If all pid and pgid are None, they are equal + Ordering::Equal + } +} + +impl PartialOrd for WaitpidKey { + fn partial_cmp(&self, other: &WaitpidKey) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for WaitpidKey { + fn eq(&self, other: &WaitpidKey) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for WaitpidKey {} + /// A context, which identifies either a process or a thread #[derive(Debug)] pub struct Context { @@ -59,7 +119,7 @@ pub struct Context { /// Context is halting parent pub vfork: bool, /// Context is being waited on - pub waitpid: Arc>, + pub waitpid: Arc>, /// Context should handle pending signals pub pending: VecDeque, /// Context should wake up at specified time diff --git a/src/context/mod.rs b/src/context/mod.rs index dc4ef3f..c715a7e 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -5,7 +5,7 @@ use alloc::heap::Heap; use core::sync::atomic::Ordering; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; -pub use self::context::{Context, ContextId, Status}; +pub use self::context::{Context, ContextId, Status, WaitpidKey}; pub use self::list::ContextList; pub use self::switch::switch; diff --git a/src/context/signal.rs b/src/context/signal.rs index f51deb4..ad70ca6 100644 --- a/src/context/signal.rs +++ b/src/context/signal.rs @@ -1,7 +1,7 @@ use alloc::arc::Arc; use core::mem; -use context::{contexts, switch, Status}; +use context::{contexts, switch, Status, WaitpidKey}; use start::usermode; use syscall; use syscall::flag::{SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU}; @@ -19,19 +19,19 @@ pub extern "C" fn signal_handler(sig: usize) { if handler == SIG_DFL { match sig { SIGCHLD => { - println!("SIGCHLD"); + // println!("SIGCHLD"); }, SIGCONT => { - println!("Continue"); + // println!("Continue"); { let contexts = contexts(); - let (pid, ppid) = { + let (pid, pgid, 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) + (context.id, context.pgid, context.ppid) }; if let Some(parent_lock) = contexts.get(ppid) { @@ -40,23 +40,26 @@ pub extern "C" fn signal_handler(sig: usize) { Arc::clone(&parent.waitpid) }; - waitpid.send(pid, 0xFFFF); + waitpid.send(WaitpidKey { + pid: Some(pid), + pgid: Some(pgid) + }, (pid, 0xFFFF)); } else { println!("{}: {} not found for continue", pid.into(), ppid.into()); } } }, SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => { - println!("Stop {}", sig); + // println!("Stop {}", sig); { let contexts = contexts(); - let (pid, ppid) = { + let (pid, pgid, 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) + (context.id, context.pgid, context.ppid) }; if let Some(parent_lock) = contexts.get(ppid) { @@ -65,7 +68,10 @@ pub extern "C" fn signal_handler(sig: usize) { Arc::clone(&parent.waitpid) }; - waitpid.send(pid, (sig << 8) | 0x7F); + waitpid.send(WaitpidKey { + pid: Some(pid), + pgid: Some(pgid) + }, (pid, (sig << 8) | 0x7F)); } else { println!("{}: {} not found for stop", pid.into(), ppid.into()); } @@ -74,14 +80,14 @@ pub extern "C" fn signal_handler(sig: usize) { unsafe { switch() }; }, _ => { - println!("Exit {}", sig); + // println!("Exit {}", sig); syscall::exit(sig); } } } else if handler == SIG_IGN { - println!("Ignore"); + // println!("Ignore"); } else { - println!("Call {:X}", handler); + // println!("Call {:X}", handler); unsafe { let mut sp = ::USER_SIGSTACK_OFFSET + ::USER_SIGSTACK_SIZE - 256; diff --git a/src/syscall/process.rs b/src/syscall/process.rs index b627d7b..b64f364 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -14,7 +14,7 @@ use paging::temporary_page::TemporaryPage; use start::usermode; use interrupt; use context; -use context::ContextId; +use context::{ContextId, WaitpidKey}; use context::file::FileDescriptor; #[cfg(not(feature="doc"))] use elf::{self, program_header}; @@ -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, SIGCONT, SIGTERM, WCONTINUED, WNOHANG, WUNTRACED}; +use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, SIG_DFL, SIGCONT, SIGTERM, WCONTINUED, WNOHANG, WUNTRACED, wifcontinued, wifstopped}; use syscall::validate::{validate_slice, validate_slice_mut}; pub fn brk(address: usize) -> Result { @@ -863,10 +863,10 @@ pub fn exit(status: usize) -> ! { } } - // PPID must be grabbed after close, as context switches could change PPID if parent exits - let ppid = { + // PGID and PPID must be grabbed after close, as context switches could change PGID or PPID if parent exits + let (pgid, ppid) = { let context = context_lock.read(); - context.ppid + (context.pgid, context.ppid) }; // Transfer child processes to parent @@ -912,7 +912,11 @@ pub fn exit(status: usize) -> ! { for (c_pid, c_status) in children { waitpid.send(c_pid, c_status); } - waitpid.send(pid, status); + + waitpid.send(WaitpidKey { + pid: Some(pid), + pgid: Some(pgid) + }, (pid, status)); } else { println!("{}: {} not found for exit vfork unblock", pid.into(), ppid.into()); } @@ -965,8 +969,6 @@ pub fn getppid() -> Result { } pub fn kill(pid: ContextId, sig: usize) -> Result { - println!("Kill {} {}", pid.into() as isize, sig); - let (ruid, euid, current_pgid) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -1109,8 +1111,6 @@ pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mu } pub fn sigreturn() -> Result { - println!("Sigreturn"); - { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -1165,14 +1165,14 @@ pub fn waitpid(pid: ContextId, status_ptr: usize, flags: usize) -> Result Option> { - if status == 0xFFFF { + if wifcontinued(status) { if flags & WCONTINUED == WCONTINUED { status_slice[0] = status; Some(Ok(w_pid)) } else { None } - } else if status & 0xFF == 0x7F { + } else if wifstopped(status) { if flags & WUNTRACED == WUNTRACED { status_slice[0] = status; Some(Ok(w_pid)) @@ -1188,17 +1188,36 @@ pub fn waitpid(pid: ContextId, status_ptr: usize, flags: usize) -> Result Result