Skip to content

Commit fb30a30

Browse files
authored
Add a way to get the raw fields out of a WaitStatus. (#1300)
1 parent ccc8cf8 commit fb30a30

3 files changed

Lines changed: 62 additions & 11 deletions

File tree

src/backend/linux_raw/process/wait.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// The functions replacing the C macros use the same names as in libc.
22
#![allow(non_snake_case, unsafe_code)]
33

4-
use linux_raw_sys::ctypes::c_int;
4+
use crate::ffi::c_int;
55
pub(crate) use linux_raw_sys::general::{
66
siginfo_t, WCONTINUED, WEXITED, WNOHANG, WNOWAIT, WSTOPPED, WUNTRACED,
77
};
@@ -42,11 +42,27 @@ pub(crate) fn WEXITSTATUS(status: u32) -> u32 {
4242
}
4343

4444
pub(crate) trait SiginfoExt {
45+
fn si_signo(&self) -> c_int;
46+
fn si_errno(&self) -> c_int;
4547
fn si_code(&self) -> c_int;
4648
unsafe fn si_status(&self) -> c_int;
4749
}
4850

4951
impl SiginfoExt for siginfo_t {
52+
#[inline]
53+
fn si_signo(&self) -> c_int {
54+
// SAFETY: This is technically a union access, but it's only a union
55+
// with padding.
56+
unsafe { self.__bindgen_anon_1.__bindgen_anon_1.si_signo }
57+
}
58+
59+
#[inline]
60+
fn si_errno(&self) -> c_int {
61+
// SAFETY: This is technically a union access, but it's only a union
62+
// with padding.
63+
unsafe { self.__bindgen_anon_1.__bindgen_anon_1.si_errno }
64+
}
65+
5066
#[inline]
5167
fn si_code(&self) -> c_int {
5268
// SAFETY: This is technically a union access, but it's only a union

src/process/wait.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,39 +142,39 @@ impl WaitIdStatus {
142142
/// Returns whether the process is currently stopped.
143143
#[inline]
144144
pub fn stopped(&self) -> bool {
145-
self.si_code() == backend::c::CLD_STOPPED
145+
self.raw_code() == bitcast!(backend::c::CLD_STOPPED)
146146
}
147147

148148
/// Returns whether the process is currently trapped.
149149
#[inline]
150150
pub fn trapped(&self) -> bool {
151-
self.si_code() == backend::c::CLD_TRAPPED
151+
self.raw_code() == bitcast!(backend::c::CLD_TRAPPED)
152152
}
153153

154154
/// Returns whether the process has exited normally.
155155
#[inline]
156156
pub fn exited(&self) -> bool {
157-
self.si_code() == backend::c::CLD_EXITED
157+
self.raw_code() == bitcast!(backend::c::CLD_EXITED)
158158
}
159159

160160
/// Returns whether the process was terminated by a signal and did not
161161
/// create a core file.
162162
#[inline]
163163
pub fn killed(&self) -> bool {
164-
self.si_code() == backend::c::CLD_KILLED
164+
self.raw_code() == bitcast!(backend::c::CLD_KILLED)
165165
}
166166

167167
/// Returns whether the process was terminated by a signal and did create a
168168
/// core file.
169169
#[inline]
170170
pub fn dumped(&self) -> bool {
171-
self.si_code() == backend::c::CLD_DUMPED
171+
self.raw_code() == bitcast!(backend::c::CLD_DUMPED)
172172
}
173173

174174
/// Returns whether the process has continued from a job control stop.
175175
#[inline]
176176
pub fn continued(&self) -> bool {
177-
self.si_code() == backend::c::CLD_CONTINUED
177+
self.raw_code() == bitcast!(backend::c::CLD_CONTINUED)
178178
}
179179

180180
/// Returns the number of the signal that stopped the process, if the
@@ -225,19 +225,45 @@ impl WaitIdStatus {
225225
}
226226
}
227227

228+
/// Return the raw `si_signo` value returned from `waitid`.
228229
#[cfg(linux_raw)]
229-
fn si_code(&self) -> u32 {
230-
self.0.si_code() as u32 // CLD_ consts are unsigned
230+
pub fn raw_signo(&self) -> crate::ffi::c_int {
231+
self.0.si_signo()
231232
}
232233

234+
/// Return the raw `si_signo` value returned from `waitid`.
233235
#[cfg(not(linux_raw))]
234-
fn si_code(&self) -> backend::c::c_int {
236+
pub fn raw_signo(&self) -> crate::ffi::c_int {
237+
self.0.si_signo
238+
}
239+
240+
/// Return the raw `si_errno` value returned from `waitid`.
241+
#[cfg(linux_raw)]
242+
pub fn raw_errno(&self) -> crate::ffi::c_int {
243+
self.0.si_errno()
244+
}
245+
246+
/// Return the raw `si_errno` value returned from `waitid`.
247+
#[cfg(not(linux_raw))]
248+
pub fn raw_errno(&self) -> crate::ffi::c_int {
249+
self.0.si_errno
250+
}
251+
252+
/// Return the raw `si_code` value returned from `waitid`.
253+
#[cfg(linux_raw)]
254+
pub fn raw_code(&self) -> crate::ffi::c_int {
255+
self.0.si_code()
256+
}
257+
258+
/// Return the raw `si_code` value returned from `waitid`.
259+
#[cfg(not(linux_raw))]
260+
pub fn raw_code(&self) -> crate::ffi::c_int {
235261
self.0.si_code
236262
}
237263

238264
#[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "netbsd")))]
239265
#[allow(unsafe_code)]
240-
fn si_status(&self) -> backend::c::c_int {
266+
fn si_status(&self) -> crate::ffi::c_int {
241267
// SAFETY: POSIX [specifies] that the `siginfo_t` returned by a
242268
// `waitid` call always has a valid `si_status` value.
243269
//

tests/process/wait.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ fn test_waitpid_none() {
2323
.unwrap();
2424
assert_eq!(pid, process::Pid::from_child(&child));
2525
assert!(status.stopped());
26+
assert_ne!(status.as_raw(), 0);
2627

2728
// Clean up the child process.
2829
unsafe { kill(child.id() as _, SIGKILL) };
@@ -50,6 +51,7 @@ fn test_waitpid_some() {
5051
.unwrap();
5152
assert_eq!(rpid, pid);
5253
assert!(status.stopped());
54+
assert_ne!(status.as_raw(), 0);
5355

5456
// Clean up the child process.
5557
unsafe { kill(child.id() as _, SIGKILL) };
@@ -77,6 +79,7 @@ fn test_waitpgid() {
7779
.unwrap();
7880
assert_eq!(pid, process::Pid::from_child(&child));
7981
assert!(status.stopped());
82+
assert_ne!(status.as_raw(), 0);
8083

8184
// Clean up the child process.
8285
unsafe { kill(child.id() as _, SIGKILL) };
@@ -116,6 +119,9 @@ fn test_waitid() {
116119
assert!(status.stopped());
117120
#[cfg(not(any(target_os = "fuchsia", target_os = "netbsd")))]
118121
assert_eq!(status.stopping_signal(), Some(SIGSTOP as _));
122+
assert_eq!(status.raw_signo(), libc::SIGCHLD);
123+
assert_eq!(status.raw_errno(), 0);
124+
assert_eq!(status.raw_code(), libc::CLD_STOPPED);
119125

120126
unsafe { kill(child.id() as _, SIGCONT) };
121127

@@ -139,6 +145,9 @@ fn test_waitid() {
139145
assert!(status.stopped());
140146
#[cfg(not(any(target_os = "fuchsia", target_os = "netbsd")))]
141147
assert_eq!(status.stopping_signal(), Some(SIGSTOP as _));
148+
assert_eq!(status.raw_signo(), libc::SIGCHLD);
149+
assert_eq!(status.raw_errno(), 0);
150+
assert_eq!(status.raw_code(), libc::CLD_STOPPED);
142151

143152
unsafe { kill(child.id() as _, SIGCONT) };
144153

0 commit comments

Comments
 (0)