1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
use core::mem; pub use libc::id_t as Id; use err::*; #[inline] pub fn fork() -> Result<Id, OsErr> { unsafe { esyscall!(FORK).map(|pid| pid as _) } } #[inline] pub fn quit(code: isize) -> ! { unsafe { #[cfg(target_os = "linux")] syscall!(EXIT_GROUP, code); syscall!(EXIT, code); ::core::intrinsics::abort() } } #[inline] pub fn pid() -> Id { unsafe { syscall!(GETPID) as _ } } #[inline] pub fn ppid() -> Id { unsafe { syscall!(GETPPID) as _ } } #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum WaitSpec { Pid(Id), Gid(Id), All } impl WaitSpec { #[inline] pub fn wait(self, flags: WaitFlags) -> Result<(WaitInfo, ::libc::rusage), OsErr> { unsafe { let (id_type, id) = self.to_wait_args(); let mut si: siginfo = mem::uninitialized(); let mut ru: ::libc::rusage = mem::uninitialized(); si.si.pid = 0; esyscall!(WAITID, id_type, id, &mut si as *mut _, flags.bits, &mut ru as *mut _)?; if 0 == si.si.pid { return Err(EWOULDBLOCK) } Ok((WaitInfo::from_c(si.si), ru)) } } #[inline] unsafe fn to_wait_args(self) -> (::libc::idtype_t, Id) { use self::WaitSpec::*; match self { Pid(pid) => (::libc::P_PID, pid), Gid(gid) => (::libc::P_PGID, gid), All => (::libc::P_ALL, mem::uninitialized()), } } } bitflags! { pub struct WaitFlags: usize { const Exit = ::libc::WEXITED as usize; const Stop = ::libc::WSTOPPED as usize; const Cont = ::libc::WCONTINUED as usize; const NoHang = ::libc::WNOHANG as usize; const NoWait = ::libc::WNOWAIT as usize; } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct WaitInfo { pid: Id, code: WaitCode, status: isize, } impl WaitInfo { #[inline] unsafe fn from_c(si: siginfo_) -> Self { WaitInfo { pid: si.pid as _, code: WaitCode::from_c(si.code), status: si.status as _, } } } #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum WaitCode { Exit = 1, Kill = 2, Dump = 3, Trap = 4, Stop = 5, Cont = 6 } impl WaitCode { #[inline] unsafe fn from_c(c: ::libc::c_int) -> Self { use self::WaitCode::*; match c { 1 => Exit, 2 => Kill, 3 => Dump, 4 => Trap, 5 => Stop, 6 => Cont, _ => mem::uninitialized() } } } #[cfg(target_os = "linux")] #[repr(C)] #[derive(Clone, Copy)] struct siginfo_ { signo: ::libc::c_int, errno: ::libc::c_int, code: ::libc::c_int, pid: ::libc::pid_t, uid: ::libc::uid_t, value: ::libc::sigval, status: ::libc::c_int, } #[repr(C)] union siginfo { si: siginfo_, pad: [u8; 0x80], }