@@ -4,48 +4,41 @@ use unistd::Pid;
4
4
5
5
use sys:: signal:: Signal ;
6
6
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" ) ) ]
28
7
libc_bitflags ! (
8
+ /// Defines optional flags for the `waitpid` function.
29
9
pub flags WaitPidFlag : c_int {
30
10
/// Returns immediately if no child has exited
31
11
WNOHANG ,
32
12
/// Returns if a child has been stopped, but isn't being traced by ptrace.
33
13
WUNTRACED ,
14
+ #[ cfg( any( target_os = "linux" ,
15
+ target_os = "android" ) ) ]
34
16
/// Waits for children that have terminated.
35
17
WEXITED ,
18
+ #[ cfg( any( target_os = "linux" ,
19
+ target_os = "android" ) ) ]
36
20
/// Waits for previously stopped children that have been resumed with `SIGCONT`.
37
21
WCONTINUED ,
22
+ #[ cfg( any( target_os = "linux" ,
23
+ target_os = "android" ) ) ]
38
24
/// Leave the child in a waitable state; a later wait call can be used to again retrieve
39
25
/// the child status information.
40
26
WNOWAIT ,
27
+ #[ cfg( any( target_os = "linux" ,
28
+ target_os = "android" ) ) ]
41
29
/// Don't wait on children of other threads in this group
42
30
__WNOTHREAD,
31
+ #[ cfg( any( target_os = "linux" ,
32
+ target_os = "android" ) ) ]
43
33
/// Wait for all children, regardless of type (clone or non-clone)
44
34
__WALL,
35
+ #[ cfg( any( target_os = "linux" ,
36
+ target_os = "android" ) ) ]
45
37
/// Wait for "clone" children only. If omitted then wait for "non-clone" children only.
46
38
/// (A "clone" child is one which delivers no signal, or a signal other than `SIGCHLD` to
47
39
/// its parent upon termination.) This option is ignored if `__WALL` is also specified.
48
40
__WCLONE,
41
+
49
42
}
50
43
) ;
51
44
@@ -54,6 +47,7 @@ libc_bitflags!(
54
47
const WSTOPPED : WaitPidFlag = WUNTRACED ;
55
48
56
49
#[ derive( Eq , PartialEq , Clone , Copy , Debug ) ]
50
+ /// Contains the status returned by the `wait` and `waitpid` functions.
57
51
pub enum WaitStatus {
58
52
/// Signifies that the process has exited, providing the PID and associated exit status.
59
53
Exited ( Pid , i8 ) ,
@@ -65,6 +59,7 @@ pub enum WaitStatus {
65
59
PtraceEvent ( Pid , Signal , c_int ) ,
66
60
/// Signifies that the process received a `SIGCONT` signal, and thus continued.
67
61
Continued ( Pid ) ,
62
+ /// if `WNOHANG` was set, this value is returned when no children have changed state.
68
63
StillAlive
69
64
}
70
65
@@ -232,6 +227,55 @@ fn decode(pid : Pid, status: i32) -> WaitStatus {
232
227
}
233
228
}
234
229
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
+
235
279
/// Waits for and returns events that are received from the given supplied process or process group
236
280
/// ID, and associated options.
237
281
///
@@ -254,31 +298,23 @@ fn decode(pid : Pid, status: i32) -> WaitStatus {
254
298
/// `SIG_IGN`.
255
299
/// - **EINTR**: `WNOHANG` was not set and either an unblocked signal or a `SIGCHLD` was caught.
256
300
/// - **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 > >
260
303
{
261
304
use self :: WaitStatus :: * ;
262
305
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 ( ) ) ;
266
308
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) } ;
274
310
275
311
Errno :: result ( res) . map ( |res| match res {
276
- 0 => StillAlive ,
312
+ 0 => StillAlive ,
277
313
res => decode ( Pid :: from_raw ( res) , status) ,
278
314
} )
279
315
}
280
316
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.
282
318
pub fn wait ( ) -> Result < WaitStatus > {
283
- waitpid ( None , None )
319
+ waitpid ( PidGroup :: AnyChild , None )
284
320
}
0 commit comments