os/uapi/
wait.rs

1//! 定义与等待子进程状态相关的标志。
2//!
3//! 这些标志用于 `waitpid` 和 `waitid` 系统调用,以指定等待行为。
4
5use core::ffi::c_int;
6
7use bitflags::bitflags;
8
9/// 子进程的状态编码(对应 waitpid/wait4 返回的 wstatus)。
10/// 包含了解析和构造状态值的方法。
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct WaitStatus {
13    raw_status: c_int,
14}
15
16const __W_CONTINUED: u32 = 0xFFFF; // 0xffff
17const __WCOREFLAG: u32 = 0x80; // 0x80 (用于 WCOREDUMP 标记)
18const __W_STOP_MAGIC: u32 = 0x7F; // 0x7f (用于 WIFSTOPPED 标记)
19
20impl WaitStatus {
21    /// 从原始的 wstatus 整数值创建一个 WaitStatus 实例。
22    pub const fn new(raw_status: c_int) -> Self {
23        Self { raw_status }
24    }
25
26    /// 获取原始状态值。
27    pub const fn raw(&self) -> c_int {
28        self.raw_status
29    }
30
31    /// __W_EXITCODE: 构造一个正常退出或因信号终止的状态值。
32    ///
33    /// 结构: (Exit Code) << 8 | (Termination Signal)
34    /// * ret: 退出码 (0-255)
35    /// * sig: 信号编号 (如果为 0 则表示正常退出)
36    pub fn exit_code(ret: u8, sig: u8) -> Self {
37        let status = ((ret as u32) << 8) | (sig as u32);
38        Self::new(status as c_int)
39    }
40
41    /// __W_STOPCODE: 构造一个子进程被停止的状态值。
42    ///
43    /// 结构: (Signal that stopped the child) << 8 | 0x7f
44    /// * sig: 导致停止的信号编号
45    pub fn stop_code(sig: u8) -> Self {
46        let status = ((sig as u32) << 8) | __W_STOP_MAGIC;
47        Self::new(status as c_int)
48    }
49
50    /// 构造一个子进程从停止状态恢复继续执行的状态值。
51    pub fn continued_code() -> Self {
52        Self::new(__W_CONTINUED as c_int)
53    }
54
55    // WTERMSIG / __WTERMSIG: 获取终止信号编号
56    /// 如果 WIFSIGNALED 为真,返回导致子进程终止的信号编号(低 7 位)。
57    pub fn termination_signal(&self) -> c_int {
58        self.raw_status & 0x7F
59    }
60
61    // WIFEXITED / __WIFEXITED: 是否正常退出
62    /// 检查状态是否表示正常终止(即终止信号为 0)。
63    pub fn is_exited(&self) -> bool {
64        self.termination_signal() == 0
65    }
66
67    // WEXITSTATUS / __WEXITSTATUS: 获取退出码
68    /// 如果 is_exited() 为真,返回子进程的退出状态码(位于第 8-15 位)。
69    pub fn exit_status(&self) -> c_int {
70        (self.raw_status >> 8) & 0xFF
71    }
72
73    // WIFSIGNALED / __WIFSIGNALED: 是否因信号终止
74    /// 检查状态是否表示子进程因未捕获的信号而终止。
75    pub fn is_signaled(&self) -> bool {
76        // C 宏逻辑:((signed char) (((status) & 0x7f) + 1) >> 1) > 0
77        // 等价于检查 (status & 0x7f) 是否在 [1, 127] 范围内
78        let term_sig = (self.raw_status & 0x7F) as u32;
79        term_sig > 0 && term_sig != __W_STOP_MAGIC
80    }
81
82    // WIFSTOPPED / __WIFSTOPPED: 是否被停止
83    /// 检查状态是否表示子进程被停止信号停止。
84    pub fn is_stopped(&self) -> bool {
85        (self.raw_status & 0xFF) as u32 == __W_STOP_MAGIC
86    }
87
88    // WSTOPSIG / __WSTOPSIG: 获取停止信号编号
89    /// 如果 is_stopped() 为真,返回导致子进程停止的信号编号。
90    /// 注意:该宏等价于 __WEXITSTATUS(status),即提取第 8-15 位。
91    pub fn stop_signal(&self) -> c_int {
92        self.exit_status()
93    }
94
95    // WIFCONTINUED / __WIFCONTINUED: 是否已恢复
96    /// 检查状态是否表示子进程已从停止状态恢复执行。
97    pub fn is_continued(&self) -> bool {
98        self.raw_status as u32 == __W_CONTINUED
99    }
100
101    // WCOREDUMP / __WCOREDUMP: 是否生成了核心转储
102    /// 检查子进程终止时是否生成了核心转储文件。
103    pub fn did_core_dump(&self) -> bool {
104        // 检查终止信号的最高位是否设置了 0x80 (__WCOREFLAG)
105        (self.raw_status as u32) & __WCOREFLAG != 0
106    }
107}
108
109bitflags! {
110    /// 等待子进程状态的选项标志。
111    /// 对应于 `waitpid` 和 `waitid` 系统调用中的参数。
112    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
113    pub struct WaitFlags: usize {
114        // --- 适用于 waitpid/wait4 的基本标志 ---
115
116        /// WNOHANG: 非阻塞等待。如果没有子进程状态立即可用,则立即返回 0。
117        const NOHANG = 0x1;
118
119        /// WUNTRACED: 报告已停止/终止的子进程状态。
120        /// 报告那些因接收到信号(如 SIGSTOP 或 SIGTTIN/SIGTTOU)而停止的子进程。
121        const UNTRACED = 0x2;
122
123        // --- 适用于 waitid 的 POSIX/XOPEN 标志 ---
124
125        /// WSTOPPED: 报告已停止的子进程状态(与 WUNTRACED 相同)。
126        const STOPPED = 0x2;
127
128        /// WEXITED: 报告已终止(死亡)的子进程状态。
129        const EXITED = 0x4;
130
131        /// WCONTINUED: 报告因收到 SIGCONT 信号而恢复执行的子进程。
132        const CONTINUED = 0x8;
133
134        /// WNOWAIT: 仅查询状态,不将子进程从 wait set 中移除 (不回收/不释放资源)。
135        const NOWAIT = 0x0100_0000;
136
137        // --- Linux/GNU 内部/扩展标志 ---
138
139        /// __WNOTHREAD: 不等待本进程组内其他线程的子进程 (仅限调用线程的子进程)。
140        const NOTHREAD = 0x2000_0000;
141
142        /// __WALL: 等待所有子进程,无论其类型(包括通过 clone() 创建的线程)。
143        const ALL = 0x4000_0000;
144
145        /// __WCLONE: 仅等待由 clone() 创建的“线程”子进程。
146        const CLONE = 0x8000_0000;
147    }
148}