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
117
118
119
120
121
122
123
124
125
126
127
128
129
|
use crate::process::Pid;
use crate::{imp, io};
use bitflags::bitflags;
bitflags! {
/// Options for modifying the behavior of wait/waitpid
pub struct WaitOptions: u32 {
/// Return immediately if no child has exited.
const NOHANG = imp::process::wait::WNOHANG as _;
/// Return if a child has stopped (but not traced via `ptrace(2)`)
const UNTRACED = imp::process::wait::WUNTRACED as _;
/// Return if a stopped child has been resumed by delivery of `SIGCONT`
const CONTINUED = imp::process::wait::WCONTINUED as _;
}
}
/// the status of the child processes the caller waited on
#[derive(Debug, Clone, Copy)]
pub struct WaitStatus(u32);
impl WaitStatus {
/// create a `WaitStatus` out of an integer.
#[inline]
pub(crate) fn new(status: u32) -> Self {
Self(status)
}
/// Converts a `WaitStatus` into its raw representation as an integer.
#[inline]
pub const fn as_raw(self) -> u32 {
self.0
}
/// Returns whether the process is currently stopped.
#[inline]
pub fn stopped(self) -> bool {
imp::process::wait::WIFSTOPPED(self.0 as _)
}
/// Returns whether the process has continued from a job control stop.
#[inline]
pub fn continued(self) -> bool {
imp::process::wait::WIFCONTINUED(self.0 as _)
}
/// Returns the number of the signal that stopped the process,
/// if the process was stopped by a signal.
#[inline]
pub fn stopping_signal(self) -> Option<u32> {
if self.stopped() {
Some(imp::process::wait::WSTOPSIG(self.0 as _) as _)
} else {
None
}
}
/// Returns the exit status number returned by the process,
/// if it exited normally.
#[inline]
pub fn exit_status(self) -> Option<u32> {
if imp::process::wait::WIFEXITED(self.0 as _) {
Some(imp::process::wait::WEXITSTATUS(self.0 as _) as _)
} else {
None
}
}
/// Returns the number of the signal that terminated the process,
/// if the process was terminated by a signal.
#[inline]
pub fn terminating_signal(self) -> Option<u32> {
if imp::process::wait::WIFSIGNALED(self.0 as _) {
Some(imp::process::wait::WTERMSIG(self.0 as _) as _)
} else {
None
}
}
}
/// `waitpid(pid, waitopts)`—Wait for a specific process to change state.
///
/// If the pid is `None`, the call will wait for any child process whose
/// process group id matches that of the calling process.
///
/// If the pid is equal to `RawPid::MAX`, the call will wait for any child
/// process.
///
/// Otherwise if the `wrapping_neg` of pid is less than pid, the call will wait
/// for any child process with a group ID equal to the `wrapping_neg` of `pid`.
///
/// Otherwise, the call will wait for the child process with the given pid.
///
/// On Success, returns the status of the selected process.
///
/// If `NOHANG` was specified in the options, and the selected child process
/// didn't change state, returns `None`.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html
/// [Linux]: https://man7.org/linux/man-pages/man2/waitpid.2.html
#[cfg(not(target_os = "wasi"))]
#[inline]
pub fn waitpid(pid: Option<Pid>, waitopts: WaitOptions) -> io::Result<Option<WaitStatus>> {
Ok(imp::process::syscalls::waitpid(pid, waitopts)?.map(|(_, status)| status))
}
/// `wait(waitopts)`—Wait for any of the children of calling process to
/// change state.
///
/// On success, returns the pid of the child process whose state changed, and
/// the status of said process.
///
/// If `NOHANG` was specified in the options, and the selected child process
/// didn't change state, returns `None`.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html
/// [Linux]: https://man7.org/linux/man-pages/man2/waitpid.2.html
#[cfg(not(target_os = "wasi"))]
#[inline]
pub fn wait(waitopts: WaitOptions) -> io::Result<Option<(Pid, WaitStatus)>> {
imp::process::syscalls::wait(waitopts)
}
|