Skip to content

Commit 98ad58a

Browse files
committed
Implement PidGroup & More Documentation
1 parent 8a24a28 commit 98ad58a

File tree

2 files changed

+75
-38
lines changed

2 files changed

+75
-38
lines changed

src/sys/wait.rs

+73-37
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,41 @@ use unistd::Pid;
44

55
use sys::signal::Signal;
66

7-
mod ffi {
8-
use libc::{pid_t, c_int};
9-
10-
extern {
11-
pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t;
12-
}
13-
}
14-
15-
#[cfg(not(any(target_os = "linux",
16-
target_os = "android")))]
17-
libc_bitflags!(
18-
pub flags WaitPidFlag: c_int {
19-
/// Returns immediately if no child has exited
20-
WNOHANG,
21-
/// Returns if a child has been stopped, but isn't being traced by ptrace.
22-
WUNTRACED,
23-
}
24-
);
25-
26-
#[cfg(any(target_os = "linux",
27-
target_os = "android"))]
287
libc_bitflags!(
8+
/// Defines optional flags for the `waitpid` function.
299
pub flags WaitPidFlag: c_int {
3010
/// Returns immediately if no child has exited
3111
WNOHANG,
3212
/// Returns if a child has been stopped, but isn't being traced by ptrace.
3313
WUNTRACED,
14+
#[cfg(any(target_os = "linux",
15+
target_os = "android"))]
3416
/// Waits for children that have terminated.
3517
WEXITED,
18+
#[cfg(any(target_os = "linux",
19+
target_os = "android"))]
3620
/// Waits for previously stopped children that have been resumed with `SIGCONT`.
3721
WCONTINUED,
22+
#[cfg(any(target_os = "linux",
23+
target_os = "android"))]
3824
/// Leave the child in a waitable state; a later wait call can be used to again retrieve
3925
/// the child status information.
4026
WNOWAIT,
27+
#[cfg(any(target_os = "linux",
28+
target_os = "android"))]
4129
/// Don't wait on children of other threads in this group
4230
__WNOTHREAD,
31+
#[cfg(any(target_os = "linux",
32+
target_os = "android"))]
4333
/// Wait for all children, regardless of type (clone or non-clone)
4434
__WALL,
35+
#[cfg(any(target_os = "linux",
36+
target_os = "android"))]
4537
/// Wait for "clone" children only. If omitted then wait for "non-clone" children only.
4638
/// (A "clone" child is one which delivers no signal, or a signal other than `SIGCHLD` to
4739
/// its parent upon termination.) This option is ignored if `__WALL` is also specified.
4840
__WCLONE,
41+
4942
}
5043
);
5144

@@ -54,6 +47,7 @@ libc_bitflags!(
5447
const WSTOPPED: WaitPidFlag = WUNTRACED;
5548

5649
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
50+
/// Contains the status returned by the `wait` and `waitpid` functions.
5751
pub enum WaitStatus {
5852
/// Signifies that the process has exited, providing the PID and associated exit status.
5953
Exited(Pid, i8),
@@ -65,6 +59,7 @@ pub enum WaitStatus {
6559
PtraceEvent(Pid, Signal, c_int),
6660
/// Signifies that the process received a `SIGCONT` signal, and thus continued.
6761
Continued(Pid),
62+
/// if `WNOHANG` was set, this value is returned when no children have changed state.
6863
StillAlive
6964
}
7065

@@ -232,6 +227,55 @@ fn decode(pid : Pid, status: i32) -> WaitStatus {
232227
}
233228
}
234229

230+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
231+
/// Designates whether the supplied `Pid` value is a process ID, process group ID,
232+
/// specifies any child of the current process's group ID, or any child of the current process.
233+
pub enum PidGroup {
234+
ProcessID(u32),
235+
ProcessGroupID(u32),
236+
AnyGroupChild,
237+
AnyChild,
238+
}
239+
240+
impl From<Pid> for PidGroup {
241+
fn from(pid: Pid) -> PidGroup {
242+
if pid > Pid::from_raw(0) {
243+
PidGroup::ProcessID(i32::from(pid) as u32)
244+
} else if pid < Pid::from_raw(-1) {
245+
PidGroup::ProcessGroupID(-i32::from(pid) as u32)
246+
} else if pid == Pid::from_raw(0) {
247+
PidGroup::AnyGroupChild
248+
} else {
249+
PidGroup::AnyChild
250+
}
251+
}
252+
}
253+
254+
impl From<i32> for PidGroup {
255+
fn from(pid: i32) -> PidGroup {
256+
if pid > 0 {
257+
PidGroup::ProcessID(pid as u32)
258+
} else if pid < -1 {
259+
PidGroup::ProcessGroupID(-pid as u32)
260+
} else if pid == 0 {
261+
PidGroup::AnyGroupChild
262+
} else {
263+
PidGroup::AnyChild
264+
}
265+
}
266+
}
267+
268+
impl Into<i32> for PidGroup {
269+
fn into(self) -> i32 {
270+
match self {
271+
PidGroup::ProcessID(pid) => pid as i32,
272+
PidGroup::ProcessGroupID(pid) => -(pid as i32),
273+
PidGroup::AnyGroupChild => 0,
274+
PidGroup::AnyChild => -1
275+
}
276+
}
277+
}
278+
235279
/// Waits for and returns events that are received from the given supplied process or process group
236280
/// ID, and associated options.
237281
///
@@ -254,31 +298,23 @@ fn decode(pid : Pid, status: i32) -> WaitStatus {
254298
/// `SIG_IGN`.
255299
/// - **EINTR**: `WNOHANG` was not set and either an unblocked signal or a `SIGCHLD` was caught.
256300
/// - **EINVAL**: The supplied options were invalid.
257-
pub fn waitpid<P,O>(pid: P, options: O) -> Result<WaitStatus>
258-
where P: Into<Option<Pid>>,
259-
O: Into<Option<WaitPidFlag>>
301+
pub fn waitpid<O>(pid: PidGroup, options: O) -> Result<WaitStatus>
302+
where O: Into<Option<WaitPidFlag>>
260303
{
261304
use self::WaitStatus::*;
262305

263-
let mut status: i32 = 0;
264-
265-
let option_bits = options.into().map_or(0, |bits| bits.bits());
306+
let mut status = 0;
307+
let options = options.into().map_or(0, |o| o.bits());
266308

267-
let res = unsafe {
268-
ffi::waitpid(pid.into().unwrap_or (
269-
Pid::from_raw(-1)).into(),
270-
&mut status as *mut c_int,
271-
option_bits
272-
)
273-
};
309+
let res = unsafe { libc::waitpid(pid.into(), &mut status as *mut c_int, options) };
274310

275311
Errno::result(res).map(|res| match res {
276-
0 => StillAlive,
312+
0 => StillAlive,
277313
res => decode(Pid::from_raw(res), status),
278314
})
279315
}
280316

281-
/// Equivalent to `waitpid(-1, None)`, which waits on any child process of the current process.
317+
/// Waits on any child of the current process.
282318
pub fn wait() -> Result<WaitStatus> {
283-
waitpid(None, None)
319+
waitpid(PidGroup::AnyChild, None)
284320
}

src/unistd.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl fmt::Display for Gid {
100100
///
101101
/// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
102102
/// passing wrong value.
103-
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
103+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd)]
104104
pub struct Pid(pid_t);
105105

106106
impl Pid {
@@ -234,6 +234,7 @@ pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
234234
let res = unsafe { libc::setpgid(pid.into(), pgid.into()) };
235235
Errno::result(res).map(drop)
236236
}
237+
237238
#[inline]
238239
pub fn getpgid(pid: Option<Pid>) -> Result<Pid> {
239240
let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) };

0 commit comments

Comments
 (0)