Skip to content

Commit 3b4fb07

Browse files
committed
Merge #732
732: Use libc definitions for wait module r=Susurrus a=Susurrus Not certain if these are all correct yet, but we can reuse a ton of logic from `libc` within the `wait` module.
2 parents b76cbee + 5967bb1 commit 3b4fb07

File tree

1 file changed

+54
-172
lines changed

1 file changed

+54
-172
lines changed

src/sys/wait.rs

Lines changed: 54 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,26 @@ 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 struct WaitPidFlag: c_int {
19-
WNOHANG;
20-
WUNTRACED;
21-
}
22-
);
23-
24-
#[cfg(any(target_os = "linux",
25-
target_os = "android"))]
267
libc_bitflags!(
278
pub struct WaitPidFlag: c_int {
289
WNOHANG;
2910
WUNTRACED;
3011
WEXITED;
3112
WCONTINUED;
32-
WNOWAIT; // Don't reap, just poll status.
33-
__WNOTHREAD; // Don't wait on children of other threads in this group
34-
__WALL; // Wait on all children, regardless of type
13+
WSTOPPED;
14+
/// Don't reap, just poll status.
15+
WNOWAIT;
16+
/// Don't wait on children of other threads in this group
17+
#[cfg(any(target_os = "android", target_os = "linux"))]
18+
__WNOTHREAD;
19+
/// Wait on all children, regardless of type
20+
#[cfg(any(target_os = "android", target_os = "linux"))]
21+
__WALL;
22+
#[cfg(any(target_os = "android", target_os = "linux"))]
3523
__WCLONE;
3624
}
3725
);
3826

39-
#[cfg(any(target_os = "linux",
40-
target_os = "android"))]
41-
const WSTOPPED: WaitPidFlag = WUNTRACED;
42-
4327
/// Possible return values from `wait()` or `waitpid()`.
4428
///
4529
/// Each status (other than `StillAlive`) describes a state transition
@@ -54,7 +38,7 @@ pub enum WaitStatus {
5438
/// The process exited normally (as with `exit()` or returning from
5539
/// `main`) with the given exit code. This case matches the C macro
5640
/// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`.
57-
Exited(Pid, i8),
41+
Exited(Pid, i32),
5842
/// The process was killed by the given signal. The third field
5943
/// indicates whether the signal generated a core dump. This case
6044
/// matches the C macro `WIFSIGNALED(status)`; the last two fields
@@ -112,179 +96,77 @@ impl WaitStatus {
11296
}
11397
}
11498

115-
#[cfg(any(target_os = "linux",
116-
target_os = "android"))]
117-
mod status {
118-
use sys::signal::Signal;
119-
use libc::c_int;
120-
use libc::SIGTRAP;
121-
122-
pub fn exited(status: i32) -> bool {
123-
(status & 0x7F) == 0
124-
}
125-
126-
pub fn exit_status(status: i32) -> i8 {
127-
((status & 0xFF00) >> 8) as i8
128-
}
129-
130-
pub fn signaled(status: i32) -> bool {
131-
((((status & 0x7f) + 1) as i8) >> 1) > 0
132-
}
133-
134-
pub fn term_signal(status: i32) -> Signal {
135-
Signal::from_c_int(status & 0x7f).unwrap()
136-
}
137-
138-
pub fn dumped_core(status: i32) -> bool {
139-
(status & 0x80) != 0
140-
}
141-
142-
pub fn stopped(status: i32) -> bool {
143-
(status & 0xff) == 0x7f
144-
}
145-
146-
pub fn stop_signal(status: i32) -> Signal {
147-
// Keep only 7 bits of the signal: the high bit
148-
// is used to indicate syscall stops, below.
149-
Signal::from_c_int((status & 0x7F00) >> 8).unwrap()
150-
}
151-
152-
pub fn syscall_stop(status: i32) -> bool {
153-
// From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
154-
// of delivering SIGTRAP | 0x80 as the signal number for syscall
155-
// stops. This allows easily distinguishing syscall stops from
156-
// genuine SIGTRAP signals.
157-
((status & 0xFF00) >> 8) == SIGTRAP | 0x80
158-
}
159-
160-
pub fn stop_additional(status: i32) -> c_int {
161-
(status >> 16) as c_int
162-
}
163-
164-
pub fn continued(status: i32) -> bool {
165-
status == 0xFFFF
166-
}
99+
fn exited(status: i32) -> bool {
100+
unsafe { libc::WIFEXITED(status) }
167101
}
168102

169-
#[cfg(any(target_os = "macos",
170-
target_os = "ios"))]
171-
mod status {
172-
use sys::signal::{Signal,SIGCONT};
173-
174-
const WCOREFLAG: i32 = 0x80;
175-
const WSTOPPED: i32 = 0x7f;
176-
177-
fn wstatus(status: i32) -> i32 {
178-
status & 0x7F
179-
}
180-
181-
pub fn exit_status(status: i32) -> i8 {
182-
((status >> 8) & 0xFF) as i8
183-
}
184-
185-
pub fn stop_signal(status: i32) -> Signal {
186-
Signal::from_c_int(status >> 8).unwrap()
187-
}
188-
189-
pub fn continued(status: i32) -> bool {
190-
wstatus(status) == WSTOPPED && stop_signal(status) == SIGCONT
191-
}
192-
193-
pub fn stopped(status: i32) -> bool {
194-
wstatus(status) == WSTOPPED && stop_signal(status) != SIGCONT
195-
}
196-
197-
pub fn exited(status: i32) -> bool {
198-
wstatus(status) == 0
199-
}
200-
201-
pub fn signaled(status: i32) -> bool {
202-
wstatus(status) != WSTOPPED && wstatus(status) != 0
203-
}
204-
205-
pub fn term_signal(status: i32) -> Signal {
206-
Signal::from_c_int(wstatus(status)).unwrap()
207-
}
208-
209-
pub fn dumped_core(status: i32) -> bool {
210-
(status & WCOREFLAG) != 0
211-
}
103+
fn exit_status(status: i32) -> i32 {
104+
unsafe { libc::WEXITSTATUS(status) }
212105
}
213106

214-
#[cfg(any(target_os = "freebsd",
215-
target_os = "openbsd",
216-
target_os = "dragonfly",
217-
target_os = "netbsd"))]
218-
mod status {
219-
use sys::signal::Signal;
220-
221-
const WCOREFLAG: i32 = 0x80;
222-
const WSTOPPED: i32 = 0x7f;
223-
224-
fn wstatus(status: i32) -> i32 {
225-
status & 0x7F
226-
}
227-
228-
pub fn stopped(status: i32) -> bool {
229-
wstatus(status) == WSTOPPED
230-
}
107+
fn signaled(status: i32) -> bool {
108+
unsafe { libc::WIFSIGNALED(status) }
109+
}
231110

232-
pub fn stop_signal(status: i32) -> Signal {
233-
Signal::from_c_int(status >> 8).unwrap()
234-
}
111+
fn term_signal(status: i32) -> Signal {
112+
Signal::from_c_int(unsafe { libc::WTERMSIG(status) }).unwrap()
113+
}
235114

236-
pub fn signaled(status: i32) -> bool {
237-
wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
238-
}
115+
fn dumped_core(status: i32) -> bool {
116+
unsafe { libc::WCOREDUMP(status) }
117+
}
239118

240-
pub fn term_signal(status: i32) -> Signal {
241-
Signal::from_c_int(wstatus(status)).unwrap()
242-
}
119+
fn stopped(status: i32) -> bool {
120+
unsafe { libc::WIFSTOPPED(status) }
121+
}
243122

244-
pub fn exited(status: i32) -> bool {
245-
wstatus(status) == 0
246-
}
123+
fn stop_signal(status: i32) -> Signal {
124+
Signal::from_c_int(unsafe { libc::WSTOPSIG(status) }).unwrap()
125+
}
247126

248-
pub fn exit_status(status: i32) -> i8 {
249-
(status >> 8) as i8
250-
}
127+
fn syscall_stop(status: i32) -> bool {
128+
// From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
129+
// of delivering SIGTRAP | 0x80 as the signal number for syscall
130+
// stops. This allows easily distinguishing syscall stops from
131+
// genuine SIGTRAP signals.
132+
unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 }
133+
}
251134

252-
pub fn continued(status: i32) -> bool {
253-
status == 0x13
254-
}
135+
fn stop_additional(status: i32) -> c_int {
136+
(status >> 16) as c_int
137+
}
255138

256-
pub fn dumped_core(status: i32) -> bool {
257-
(status & WCOREFLAG) != 0
258-
}
139+
fn continued(status: i32) -> bool {
140+
unsafe { libc::WIFCONTINUED(status) }
259141
}
260142

261143
fn decode(pid : Pid, status: i32) -> WaitStatus {
262-
if status::exited(status) {
263-
WaitStatus::Exited(pid, status::exit_status(status))
264-
} else if status::signaled(status) {
265-
WaitStatus::Signaled(pid, status::term_signal(status), status::dumped_core(status))
266-
} else if status::stopped(status) {
144+
if exited(status) {
145+
WaitStatus::Exited(pid, exit_status(status))
146+
} else if signaled(status) {
147+
WaitStatus::Signaled(pid, term_signal(status), dumped_core(status))
148+
} else if stopped(status) {
267149
cfg_if! {
268150
if #[cfg(any(target_os = "linux", target_os = "android"))] {
269151
fn decode_stopped(pid: Pid, status: i32) -> WaitStatus {
270-
let status_additional = status::stop_additional(status);
271-
if status::syscall_stop(status) {
152+
let status_additional = stop_additional(status);
153+
if syscall_stop(status) {
272154
WaitStatus::PtraceSyscall(pid)
273155
} else if status_additional == 0 {
274-
WaitStatus::Stopped(pid, status::stop_signal(status))
156+
WaitStatus::Stopped(pid, stop_signal(status))
275157
} else {
276-
WaitStatus::PtraceEvent(pid, status::stop_signal(status), status::stop_additional(status))
158+
WaitStatus::PtraceEvent(pid, stop_signal(status), stop_additional(status))
277159
}
278160
}
279161
} else {
280162
fn decode_stopped(pid: Pid, status: i32) -> WaitStatus {
281-
WaitStatus::Stopped(pid, status::stop_signal(status))
163+
WaitStatus::Stopped(pid, stop_signal(status))
282164
}
283165
}
284166
}
285167
decode_stopped(pid, status)
286168
} else {
287-
assert!(status::continued(status));
169+
assert!(continued(status));
288170
WaitStatus::Continued(pid)
289171
}
290172
}
@@ -299,7 +181,7 @@ pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Re
299181
None => 0
300182
};
301183

302-
let res = unsafe { ffi::waitpid(pid.into().unwrap_or(Pid::from_raw(-1)).into(), &mut status as *mut c_int, option_bits) };
184+
let res = unsafe { libc::waitpid(pid.into().unwrap_or(Pid::from_raw(-1)).into(), &mut status as *mut c_int, option_bits) };
303185

304186
Ok(match try!(Errno::result(res)) {
305187
0 => StillAlive,

0 commit comments

Comments
 (0)