diff --git a/src/context/context.rs b/src/context/context.rs index 0ae9109607..67eb728c5d 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -16,8 +16,7 @@ use crate::{ memory::{allocate_p2frame, deallocate_p2frame, Enomem, Frame, RaiiFrame}, paging::{RmmA, RmmArch}, percpu::PercpuBlock, - scheme::{CallerCtx, FileHandle, SchemeNamespace}, - sync::WaitMap, + scheme::FileHandle, }; use crate::syscall::error::{Error, Result, EAGAIN, ESRCH}; @@ -207,7 +206,7 @@ pub struct SignalState { } impl Context { - pub fn new(cid: ContextId, pid: ContextId, process: Arc>) -> Result { + pub fn new(cid: ContextId, pid: ProcessId, process: Arc>) -> Result { let this = Context { cid, pid, @@ -413,13 +412,6 @@ impl Context { core::mem::replace(&mut self.addr_space, addr_space) } - pub fn caller_ctx(&self) -> CallerCtx { - CallerCtx { - pid: self.pid.into(), - uid: self.euid, - gid: self.egid, - } - } fn can_access_regs(&self) -> bool { self.userspace diff --git a/src/context/list.rs b/src/context/list.rs index 1b71f7253f..813fb53fbf 100644 --- a/src/context/list.rs +++ b/src/context/list.rs @@ -1,11 +1,11 @@ use alloc::{collections::BTreeMap, sync::Arc}; -use core::iter; +use spin::RwLock; use spinning_top::RwSpinlock; use super::{ context::{Context, ContextId, Kstack}, - memory::AddrSpaceWrapper, + memory::AddrSpaceWrapper, process::{Process, ProcessId}, }; use crate::{ interrupt::InterruptStack, @@ -53,22 +53,26 @@ impl ContextList { pub(crate) fn insert_context_raw( &mut self, - id: ContextId, + cid: ContextId, + pid: ProcessId, + process: Arc>, ) -> Result<&Arc>> { assert!(self .map // TODO - .insert(id, Arc::new(RwSpinlock::new(Context::new(id, id)?))) + .insert(cid, Arc::new(RwSpinlock::new(Context::new(cid, pid, process)?))) .is_none()); Ok(self .map - .get(&id) + .get(&cid) .expect("Failed to insert new context. ID is out of bounds.")) } /// Create a new context. - pub fn new_context(&mut self) -> Result<&Arc>> { + pub fn new_context(&mut self, process: Arc>) -> Result<&Arc>> { + let pid = process.read().pid; + // Zero is not a valid context ID, therefore add 1. // // FIXME: Ensure the number of CPUs can't switch between new_context calls. @@ -91,7 +95,7 @@ impl ContextList { let id = ContextId::from(self.next_id); self.next_id += 1; - self.insert_context_raw(id) + self.insert_context_raw(id, pid, process) } /// Spawn a context from a function. diff --git a/src/context/process.rs b/src/context/process.rs index aa6d03667c..ea9fe28940 100644 --- a/src/context/process.rs +++ b/src/context/process.rs @@ -1,3 +1,5 @@ +use core::ops::{Deref, DerefMut}; + // TODO: move all this code to userspace use alloc::collections::BTreeMap; use alloc::sync::{Arc, Weak}; @@ -8,7 +10,7 @@ use spinning_top::RwSpinlock; use syscall::{Error, Result, ESRCH}; -use crate::scheme::SchemeNamespace; +use crate::scheme::{CallerCtx, SchemeNamespace}; use crate::sync::WaitMap; use crate::context::{self, Context, WaitpidKey}; @@ -17,6 +19,14 @@ int_like!(ProcessId, usize); #[derive(Debug)] pub struct Process { + pub info: ProcessInfo, + /// Context is being waited on + pub waitpid: Arc>, + /// Threads of process + pub threads: Vec>>, +} +#[derive(Debug, Clone, Copy)] +pub struct ProcessInfo { /// The process ID of this process pub pid: ProcessId, /// The group ID of this process @@ -39,46 +49,47 @@ pub struct Process { pub ens: SchemeNamespace, /// Process umask pub umask: usize, - /// Context is being waited on - pub waitpid: WaitMap, - pub threads: Vec>>, +} +impl Deref for Process { + type Target = ProcessInfo; + + fn deref(&self) -> &Self::Target { + &self.info + } +} +impl DerefMut for Process { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.info + } } pub static PROCESSES: RwLock>>> = RwLock::new(BTreeMap::new()); /// Get an iterator of all parents pub fn ancestors( - list: &BTreeSet, + list: &BTreeMap>>, id: ProcessId, -) -> impl Iterator>)> + '_ { +) -> impl Iterator>)> + '_ { core::iter::successors( list.get(&id).map(|process| (id, process)), move |(_id, process)| { - let context = process.read(); + let process = process.read(); let id = process.ppid; - list.get(&id).map(|context| (id, context)) + list.get(&id).map(|process| (id, process)) }, ) } -impl Ord for Process { - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - Ord::cmp(&self.pid, &other.pid) - } -} -impl PartialOrd for Process { - fn partial_cmp(&self, other: &Self) -> Option { - Some(Ord::cmp(&self.pid, &other.pid)) - } -} - pub fn current() -> Result>> { let pid = context::current()?.read().pid; - PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH)) + Ok(Arc::clone(PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?)) } -impl PartialEq for Process { - fn eq(&self, other: &Self) -> bool { - Ord::cmp(self, other) == core::cmp::Ordering::Equal +impl Process { + pub fn caller_ctx(&self) -> CallerCtx { + CallerCtx { + pid: self.pid.into(), + uid: self.euid, + gid: self.egid, + } } } -impl Eq for Process {} diff --git a/src/context/switch.rs b/src/context/switch.rs index 5b86fb2a09..ac9cbcfbe9 100644 --- a/src/context/switch.rs +++ b/src/context/switch.rs @@ -25,12 +25,6 @@ unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> Update return UpdateResult::Skip; } - // Ignore contexts stopped by ptrace - // TODO: ContextStatus::HardBlocked? - if context.ptrace_stop { - return UpdateResult::Skip; - } - // Ignore contexts assigned to other CPUs if !context.sched_affinity.contains(cpu_id) { return UpdateResult::Skip; @@ -201,7 +195,7 @@ pub fn switch() -> SwitchResult { })); let (ptrace_session, ptrace_flags) = if let Some((session, bp)) = ptrace::sessions() - .get(&next_context.cid) + .get(&next_context.pid) .map(|s| (Arc::downgrade(s), s.data.lock().breakpoint)) { (Some(session), bp.map_or(PtraceFlags::empty(), |f| f.flags)) diff --git a/src/ptrace.rs b/src/ptrace.rs index ed03ea10ee..b44faade6d 100644 --- a/src/ptrace.rs +++ b/src/ptrace.rs @@ -3,7 +3,7 @@ //! of the scheme. use crate::{ - context::{self, ContextId}, + context::{self, process::ProcessId}, event, percpu::PercpuBlock, scheme::GlobalSchemes, @@ -82,7 +82,7 @@ pub struct Session { pub tracer: WaitCondition, } impl Session { - pub fn with_session(pid: ContextId, callback: F) -> Result + pub fn with_session(pid: ProcessId, callback: F) -> Result where F: FnOnce(&Session) -> Result, { @@ -97,7 +97,7 @@ impl Session { } } -type SessionMap = HashMap>; +type SessionMap = HashMap>; static SESSIONS: Once> = Once::new(); @@ -113,7 +113,7 @@ fn sessions_mut() -> RwLockWriteGuard<'static, SessionMap> { /// Try to create a new session, but fail if one already exists for this /// process -pub fn try_new_session(pid: ContextId, file_id: usize) -> bool { +pub fn try_new_session(pid: ProcessId, file_id: usize) -> bool { let mut sessions = sessions_mut(); match sessions.entry(pid) { @@ -135,7 +135,7 @@ pub fn try_new_session(pid: ContextId, file_id: usize) -> bool { /// Remove the session from the list of open sessions and notify any /// waiting processes -pub fn close_session(pid: ContextId) { +pub fn close_session(pid: ProcessId) { if let Some(session) = sessions_mut().remove(&pid) { session.tracer.notify(); session.tracee.notify(); @@ -148,7 +148,7 @@ pub fn close_session(pid: ContextId) { /// session will *actually* be closed. This is partly to ensure ENOSRCH is /// returned rather than ENODEV (which occurs when there's no session - should /// never really happen). -pub fn close_tracee(pid: ContextId) { +pub fn close_tracee(pid: ProcessId) { if let Some(session) = sessions().get(&pid) { session.tracer.notify(); @@ -158,7 +158,7 @@ pub fn close_tracee(pid: ContextId) { } /// Returns true if a session is attached to this process -pub fn is_traced(pid: ContextId) -> bool { +pub fn is_traced(pid: ProcessId) -> bool { sessions().contains_key(&pid) } @@ -213,7 +213,7 @@ pub(crate) struct Breakpoint { /// /// Note: Don't call while holding any locks or allocated data, this will /// switch contexts and may in fact just never terminate. -pub fn wait(pid: ContextId) -> Result<()> { +pub fn wait(pid: ProcessId) -> Result<()> { loop { let session = { let sessions = sessions(); diff --git a/src/scheme/root.rs b/src/scheme/root.rs index c1921c19cb..5e5d991f66 100644 --- a/src/scheme/root.rs +++ b/src/scheme/root.rs @@ -8,7 +8,7 @@ use spin::RwLock; use syscall::O_FSYNC; use crate::{ - context::{self, file::InternalFlags}, + context::{self, file::InternalFlags, process}, scheme::{ self, user::{UserInner, UserScheme}, @@ -115,12 +115,7 @@ impl KernelScheme for RootScheme { Ok(OpenResult::SchemeLocal(id, InternalFlags::empty())) } else if path.is_empty() { - let scheme_ns = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.ens - }; + let scheme_ns = process::current()?.read().ens; let mut data = Vec::new(); { diff --git a/src/scheme/sys/context.rs b/src/scheme/sys/context.rs index 7f848a268a..80cd3cabc9 100644 --- a/src/scheme/sys/context.rs +++ b/src/scheme/sys/context.rs @@ -103,25 +103,26 @@ pub fn resource() -> Result> { } else { format!("{} B", memory) }; + let process = context.process.read(); string.push_str(&format!( "{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<11}{:<12}{:<8}{}\n", context.pid.get(), - context.pgid.get(), - context.ppid.get(), - context.session_id.get(), - context.ruid, - context.rgid, - context.rns.get(), - context.euid, - context.egid, - context.ens.get(), + process.pgid.get(), + process.ppid.get(), + process.session_id.get(), + process.ruid, + process.rgid, + process.rns.get(), + process.euid, + process.egid, + process.ens.get(), stat_string, cpu_string, affinity, cpu_time_string, memory_string, - context.name + context.name, )); } } diff --git a/src/scheme/sys/scheme.rs b/src/scheme/sys/scheme.rs index 2c64e61258..8b137cbaf9 100644 --- a/src/scheme/sys/scheme.rs +++ b/src/scheme/sys/scheme.rs @@ -1,17 +1,12 @@ use alloc::vec::Vec; use crate::{ - context, scheme, - syscall::error::{Error, Result, ESRCH}, + context::process, scheme, + syscall::error::{Error, Result}, }; pub fn resource() -> Result> { - let scheme_ns = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.ens - }; + let scheme_ns = process::current()?.read().ens; let mut data = Vec::new(); diff --git a/src/scheme/sys/scheme_num.rs b/src/scheme/sys/scheme_num.rs index 9a6dc23bee..1bd70cb713 100644 --- a/src/scheme/sys/scheme_num.rs +++ b/src/scheme/sys/scheme_num.rs @@ -1,17 +1,12 @@ use alloc::vec::Vec; use crate::{ - context, scheme, + context::process, scheme, syscall::error::{Error, Result, ESRCH}, }; pub fn resource() -> Result> { - let scheme_ns = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.ens - }; + let scheme_ns = process::current()?.read().ens; let mut data = Vec::new(); diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 7562ebdff7..548ce2a04a 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -21,14 +21,10 @@ use syscall::{ use crate::{ context::{ - self, - context::HardBlockedReason, - file::{FileDescription, FileDescriptor, InternalFlags}, - memory::{ + self, context::HardBlockedReason, file::{FileDescription, FileDescriptor, InternalFlags}, memory::{ AddrSpace, AddrSpaceWrapper, BorrowedFmapSource, Grant, GrantFileRef, MmapMode, PageSpan, DANGLING, - }, - BorrowedHtBuf, Context, Status, + }, process, BorrowedHtBuf, Context, Status }, event, memory::Frame, @@ -236,7 +232,7 @@ impl UserInner { } pub fn call(&self, opcode: Opcode, args: impl Args) -> Result { - let ctx = context::current()?.read().caller_ctx(); + let ctx = process::current()?.read().caller_ctx(); match self.call_extended(ctx, None, opcode, args)? { Response::Regular(code, _) => Error::demux(code), Response::Fd(_) => Err(Error::new(EIO)), @@ -1355,10 +1351,10 @@ impl KernelScheme for UserScheme { fn fchown(&self, file: usize, uid: u32, gid: u32) -> Result<()> { { - let context_lock = context::current()?; - let context = context_lock.read(); - if context.euid != 0 { - if uid != context.euid || gid != context.egid { + let process_lock = process::current()?; + let process = process_lock.read(); + if process.euid != 0 { + if uid != process.euid || gid != process.egid { return Err(Error::new(EPERM)); } } @@ -1543,7 +1539,7 @@ impl KernelScheme for UserScheme { fn kfunmap(&self, number: usize, offset: usize, size: usize, flags: MunmapFlags) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let ctx = context::current()?.read().caller_ctx(); + let ctx = process::current()?.read().caller_ctx(); let res = inner.call_extended( ctx, None, @@ -1565,7 +1561,7 @@ impl KernelScheme for UserScheme { ) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let ctx = context::current()?.read().caller_ctx(); + let ctx = process::current()?.read().caller_ctx(); let res = inner.call_extended(ctx, Some(desc), Opcode::Sendfd, [number, flags.bits()])?; match res { @@ -1603,7 +1599,7 @@ fn uid_gid_hack_merge([uid, gid]: [u32; 2]) -> u64 { u64::from(uid) | (u64::from(gid) << 32) } fn current_uid_gid() -> Result<[u32; 2]> { - Ok(match context::current()?.read() { - ref ctx => [ctx.euid, ctx.egid], + Ok(match process::current()?.read() { + ref p => [p.euid, p.egid], }) } diff --git a/src/syscall/driver.rs b/src/syscall/driver.rs index 08d93a97df..dcc1523d26 100644 --- a/src/syscall/driver.rs +++ b/src/syscall/driver.rs @@ -1,19 +1,15 @@ use alloc::sync::Arc; use crate::{ - context, + context::{self, process}, paging::VirtualAddress, syscall::error::{Error, Result, EFAULT, EPERM, ESRCH}, }; fn enforce_root() -> Result<()> { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - if context.euid == 0 { - Ok(()) - } else { - Err(Error::new(EPERM)) + if process::current()?.read().euid != 0 { + return Err(Error::new(EPERM)); } + Ok(()) } #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index f971a53a6d..f4dd9f3310 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -111,8 +111,8 @@ pub fn open(raw_path: UserSliceRo, flags: usize) -> Result { /// rmdir syscall pub fn rmdir(raw_path: UserSliceRo) -> Result<()> { - let (scheme_ns, caller_ctx) = match context::current()?.read() { - ref context => (context.ens, context.caller_ctx()), + let (scheme_ns, caller_ctx) = match process::current()?.read() { + ref process => (process.ens, process.caller_ctx()), }; /* @@ -135,8 +135,8 @@ pub fn rmdir(raw_path: UserSliceRo) -> Result<()> { /// Unlink syscall pub fn unlink(raw_path: UserSliceRo) -> Result<()> { - let (scheme_ns, caller_ctx) = match context::current()?.read() { - ref context => (context.ens, context.caller_ctx()), + let (scheme_ns, caller_ctx) = match process::current()?.read() { + ref process => (process.ens, process.caller_ctx()), }; /* let mut path_buf = BorrowedHtBuf::head()?; @@ -159,8 +159,7 @@ pub fn unlink(raw_path: UserSliceRo) -> Result<()> { /// Close syscall pub fn close(fd: FileHandle) -> Result<()> { let file = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context_lock = context::current()?; let context = context_lock.read(); context.remove_file(fd).ok_or(Error::new(EBADF))? }; @@ -169,12 +168,8 @@ pub fn close(fd: FileHandle) -> Result<()> { } fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result { - let (file, caller_ctx) = match context::current()?.read() { - ref context => ( - context.get_file(fd).ok_or(Error::new(EBADF))?, - context.caller_ctx(), - ), - }; + let caller_ctx = process::current()?.read().caller_ctx(); + let file = context::current()?.read().get_file(fd).ok_or(Error::new(EBADF))?; if user_buf.is_empty() { Ok(FileDescriptor { @@ -355,17 +350,17 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result { } pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result<()> { - let (file, caller_ctx, scheme_ns) = match context::current()?.read() { - ref context => ( - context.get_file(fd).ok_or(Error::new(EBADF))?, + let (caller_ctx, scheme_ns) = match process::current()?.read() { + ref process => ( CallerCtx { - uid: context.euid, - gid: context.egid, - pid: context.pid.get(), + uid: process.euid, + gid: process.egid, + pid: process.pid.get(), }, - context.ens, + process.ens, ), }; + let file = context::current()?.read().get_file(fd).ok_or(Error::new(EBADF))?; /* let mut path_buf = BorrowedHtBuf::head()?; diff --git a/src/syscall/privilege.rs b/src/syscall/privilege.rs index ea69478c79..05c7df2fd8 100644 --- a/src/syscall/privilege.rs +++ b/src/syscall/privilege.rs @@ -1,7 +1,7 @@ use alloc::vec::Vec; use crate::{ - context::{self, process}, + context::process, scheme::{self, SchemeNamespace}, syscall::error::*, }; diff --git a/src/syscall/process.rs b/src/syscall/process.rs index e101db66cb..f5e6174968 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -6,7 +6,7 @@ use rmm::Arch; use spin::RwLock; use crate::context::{ - memory::{AddrSpace, Grant, PageSpan}, process::{self, ProcessId}, WaitpidKey + memory::{AddrSpace, Grant, PageSpan}, process::{self, ProcessId, ProcessInfo}, WaitpidKey }; use crate::{ @@ -38,7 +38,7 @@ pub fn exit(status: usize) -> ! { let close_files; let addrspace_opt; - let pid = { + let (pid, process_lock) = { let mut context = context_lock.write(); close_files = Arc::try_unwrap(mem::take(&mut context.files)) .map_or_else(|_| Vec::new(), RwLock::into_inner); @@ -47,7 +47,7 @@ pub fn exit(status: usize) -> ! { .and_then(|a| Arc::try_unwrap(a).ok()); drop(context.syscall_head.take()); drop(context.syscall_tail.take()); - context.pid + (context.pid, Arc::clone(&context.process)) }; // Files must be closed while context is valid so that messages can be passed @@ -60,34 +60,29 @@ pub fn exit(status: usize) -> ! { // 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(); - let process = context.process.read(); + let process = process_lock.read(); (process.pgid, process.ppid) }; let _ = kill(ppid, SIGCHLD, true); - // Transfer child processes to parent (TODO: init) + // Transfer child processes to parent (TODO: to init) { let processes = context::process::PROCESSES.read(); - for (pid, process_lock) in processes.iter() { - let mut process = process_lock.write(); + for (_child_pid, child_process_lock) in processes.iter() { + let mut process = child_process_lock.write(); if process.ppid == pid { process.ppid = ppid; } } } - let children = { - let mut context = context_lock.write(); + context_lock.write().status = context::Status::Exited(status); - context.status = context::Status::Exited(status); - - context.waitpid.receive_all() - }; + let children = process_lock.write().waitpid.receive_all(); { - let contexts = context::contexts(); - if let Some(parent_lock) = contexts.get(ppid) { + let processes = process::PROCESSES.read(); + if let Some(parent_lock) = processes.get(&ppid) { let waitpid = Arc::clone(&parent_lock.write().waitpid); for (c_pid, c_status) in children { @@ -121,7 +116,7 @@ pub fn getpgid(pid: ProcessId) -> Result { let process_lock = if pid.get() == 0 { process::current()? } else { - Arc::clone(process::PROCESSES.get(&pid).ok_or(Error::new(ESRCH))?) + Arc::clone(process::PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?) }; let process = process_lock.read(); Ok(process.pgid) @@ -133,7 +128,7 @@ pub fn getppid() -> Result { pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { let (ruid, euid, current_pgid) = { - let process_lock = process::current?; + let process_lock = process::current()?; let process = process_lock.read(); (process.ruid, process.euid, process.pgid) }; @@ -172,11 +167,11 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { }, } - let mut send = |context: &mut context::Context| -> SendResult { + let mut send = |context: &mut context::Context, proc: &ProcessInfo| -> SendResult { let is_self = context.cid == context::current_cid(); // Non-root users cannot kill arbitrarily. - if euid != 0 && euid != context.ruid && ruid != context.ruid { + if euid != 0 && euid != proc.ruid && ruid != proc.ruid { return SendResult::Forbidden; } // If sig = 0, test that process exists and can be signalled, but don't send any @@ -204,8 +199,8 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { } // POSIX XSI allows but does not reqiure SIGCHLD to be sent when SIGCONT occurs. SendResult::SucceededSigcont { - ppid: context.ppid, - pgid: context.pgid, + ppid: proc.ppid, + pgid: proc.pgid, } } else if sig == SIGSTOP || (matches!(sig, SIGTTIN | SIGTTOU | SIGTSTP) @@ -219,8 +214,8 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { ctl.word[0].fetch_and(!sig_bit(SIGCONT), Ordering::Relaxed); } SendResult::SucceededSigchld { - ppid: context.ppid, - pgid: context.pgid, + ppid: proc.ppid, + pgid: proc.pgid, orig_signal: sig, } } else if sig == SIGKILL { @@ -276,14 +271,11 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { } SendResult::SucceededSigcont { ppid, pgid } => { sent += 1; - let waitpid = Arc::clone( &process::PROCESSES.read() .get(&ppid) .ok_or(Error::new(ESRCH))? .read() - .waitpid, - ); - waitpid.send( + .waitpid.send( WaitpidKey { pid: Some(pid), pgid: Some(pgid), @@ -299,22 +291,29 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { // Send to a single process if let Some(process_lock) = processes.get(&pid) { found += 1; - let result = send(&mut *process_lock.write()); + let (context_lock, info) = { + let process = process_lock.read(); + (process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info) + }; + let mut context = context_lock.write(); + let result = send(&mut *context, &info); handle_send(pid, result)?; } } else if pid.get() == 1_usize.wrapping_neg() { // Send to every process with permission, except for init for (pid, process_lock) in processes.iter() { - let mut process = process_lock.write(); + let (context_lock, info) = { + let process = process_lock.read(); + (process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info) + }; - if process.pid.get() <= 2 { + if info.pid.get() <= 2 { continue; } found += 1; - let context_lock = process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?; - let context = context_lock.write(); + let mut context = context_lock.write(); - let result = send(&mut *context); + let result = send(&mut *context, &info); drop(context); handle_send(*pid, result)?; } @@ -327,14 +326,18 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { // Send to every process in the process group whose ID for (pid, process_lock) in processes.iter() { - let mut context = process_lock.write(); + let (context_lock, info) = { + let process = process_lock.read(); + (process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info) + }; - if context.pgid != pgid { + if info.pgid != pgid { continue; } found += 1; - let result = send(&mut *context); + let mut context = context_lock.write(); + let result = send(&mut *context, &info); drop(context); handle_send(*pid, result)?; @@ -429,11 +432,12 @@ pub fn waitpid( status_ptr: Option, flags: WaitFlags, ) -> Result { - let (ppid, process_lock) = { - let process_lock = process::current()?; + let process_lock = process::current()?; + let (ppid, waitpid) = { let process = process_lock.read(); - (process.pid, process_lock) + (process.ppid, Arc::clone(&process.waitpid)) }; + let write_status = |value| { status_ptr .map(|ptr| ptr.write_usize(value)) @@ -464,8 +468,8 @@ pub fn waitpid( { let mut found = false; - let contexts = process::PROCESSES.read(); - for (_id, process_lock) in processs.iter() { + let processes = process::PROCESSES.read(); + for (_id, process_lock) in processes.iter() { let process = process_lock.read(); if process.ppid == ppid { found = true; @@ -477,7 +481,6 @@ pub fn waitpid( return Err(Error::new(ECHILD)); } } - if flags & WNOHANG == WNOHANG { if let Some((_wid, (w_pid, status))) = waitpid.receive_any_nonblock() { grim_reaper(w_pid, status) @@ -535,6 +538,9 @@ pub fn waitpid( let process = process_lock.read(); if process.ppid != ppid { + return Err(Error::new(ECHILD)); + // TODO + /* println!( "TODO: Hack for rustc - changing ppid of {} from {} to {}", process.pid.get(), @@ -542,24 +548,26 @@ pub fn waitpid( ppid.get() ); process.ppid = ppid; - //return Err(Error::new(ECHILD)); Some(context.status.clone()) + */ } else { None } }; if let Some(context::Status::Exited(status)) = hack_status { - let _ = waitpid.receive_nonblock(&WaitpidKey { + /*let _ = waitpid.receive_nonblock(&WaitpidKey { pid: Some(pid), pgid: None, }); - grim_reaper(pid, status) + grim_reaper(pid, status)*/ + unreachable!() } else if flags & WNOHANG == WNOHANG { - if let Some((w_pid, status)) = waitpid.receive_nonblock(&WaitpidKey { + let res = waitpid.receive_nonblock(&WaitpidKey { pid: Some(pid), pgid: None, - }) { + }); + if let Some((w_pid, status)) = res { grim_reaper(w_pid, status) } else { Some(Ok(ProcessId::from(0)))