rustix/backend/linux_raw/process/
wait.rs

1// The functions replacing the C macros use the same names as in libc.
2#![allow(non_snake_case, unsafe_code)]
3
4use crate::ffi::c_int;
5pub(crate) use linux_raw_sys::general::{
6    siginfo_t, WCONTINUED, WEXITED, WNOHANG, WNOWAIT, WSTOPPED, WUNTRACED,
7};
8
9#[inline]
10pub(crate) fn WIFSTOPPED(status: i32) -> bool {
11    (status & 0xff) == 0x7f
12}
13
14#[inline]
15pub(crate) fn WSTOPSIG(status: i32) -> i32 {
16    (status >> 8) & 0xff
17}
18
19#[inline]
20pub(crate) fn WIFCONTINUED(status: i32) -> bool {
21    status == 0xffff
22}
23
24#[inline]
25pub(crate) fn WIFSIGNALED(status: i32) -> bool {
26    ((status & 0x7f) + 1) as i8 >= 2
27}
28
29#[inline]
30pub(crate) fn WTERMSIG(status: i32) -> i32 {
31    status & 0x7f
32}
33
34#[inline]
35pub(crate) fn WIFEXITED(status: i32) -> bool {
36    (status & 0x7f) == 0
37}
38
39#[inline]
40pub(crate) fn WEXITSTATUS(status: i32) -> i32 {
41    (status >> 8) & 0xff
42}
43
44pub(crate) trait SiginfoExt {
45    fn si_signo(&self) -> c_int;
46    fn si_errno(&self) -> c_int;
47    fn si_code(&self) -> c_int;
48    unsafe fn si_status(&self) -> c_int;
49}
50
51impl 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
66    #[inline]
67    fn si_code(&self) -> c_int {
68        // SAFETY: This is technically a union access, but it's only a union
69        // with padding.
70        unsafe { self.__bindgen_anon_1.__bindgen_anon_1.si_code }
71    }
72
73    /// Return the exit status or signal number recorded in a `siginfo_t`.
74    ///
75    /// # Safety
76    ///
77    /// `si_signo` must equal `SIGCHLD` (as it is guaranteed to do after a
78    /// `waitid` call).
79    #[inline]
80    unsafe fn si_status(&self) -> c_int {
81        self.__bindgen_anon_1
82            .__bindgen_anon_1
83            ._sifields
84            ._sigchld
85            ._status
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    #[test]
94    fn test_libc_correspondence() {
95        for status in [
96            0,
97            1,
98            63,
99            64,
100            65,
101            127,
102            128,
103            129,
104            255,
105            256,
106            257,
107            4095,
108            4096,
109            4097,
110            i32::MAX,
111            i32::MIN,
112            u32::MAX as i32,
113        ] {
114            assert_eq!(WIFSTOPPED(status), libc::WIFSTOPPED(status));
115            assert_eq!(WSTOPSIG(status), libc::WSTOPSIG(status));
116            assert_eq!(WIFCONTINUED(status), libc::WIFCONTINUED(status));
117            assert_eq!(WIFSIGNALED(status), libc::WIFSIGNALED(status));
118            assert_eq!(WTERMSIG(status), libc::WTERMSIG(status));
119            assert_eq!(WIFEXITED(status), libc::WIFEXITED(status));
120            assert_eq!(WEXITSTATUS(status), libc::WEXITSTATUS(status));
121        }
122    }
123}