Skip to main content

starnix_core/task/
exit_status.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::ptrace::PtraceEvent;
6use crate::signals::SignalInfo;
7use starnix_uapi::{CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED};
8
9#[derive(Clone, Debug, Eq, PartialEq)]
10pub enum ExitStatus {
11    Exit(u8),
12    Kill(SignalInfo),
13    CoreDump(SignalInfo),
14    // The second field for Stop and Continue contains the type of ptrace stop
15    // event that made it stop / continue, if applicable (PTRACE_EVENT_STOP,
16    // PTRACE_EVENT_FORK, etc)
17    Stop(SignalInfo, PtraceEvent),
18    Continue(SignalInfo, PtraceEvent),
19}
20
21impl ExitStatus {
22    /// Converts the given exit status to a status code suitable for returning from wait syscalls.
23    pub fn wait_status(&self) -> i32 {
24        match self {
25            ExitStatus::Exit(status) => (*status as i32) << 8,
26            ExitStatus::Kill(siginfo) => siginfo.signal.number() as i32,
27            ExitStatus::CoreDump(siginfo) => (siginfo.signal.number() as i32) | 0x80,
28            ExitStatus::Continue(siginfo, trace_event) => {
29                let trace_event_val = *trace_event as u32;
30                if trace_event_val != 0 {
31                    (siginfo.signal.number() as i32) | (trace_event_val << 16) as i32
32                } else {
33                    0xffff
34                }
35            }
36            ExitStatus::Stop(siginfo, trace_event) => {
37                let trace_event_val = *trace_event as u32;
38                (0x7f + ((siginfo.signal.number() as i32) << 8)) | (trace_event_val << 16) as i32
39            }
40        }
41    }
42
43    pub fn signal_info_code(&self) -> i32 {
44        match self {
45            ExitStatus::Exit(_) => CLD_EXITED as i32,
46            ExitStatus::Kill(_) => CLD_KILLED as i32,
47            ExitStatus::CoreDump(_) => CLD_DUMPED as i32,
48            ExitStatus::Stop(_, _) => CLD_STOPPED as i32,
49            ExitStatus::Continue(_, _) => CLD_CONTINUED as i32,
50        }
51    }
52
53    pub fn signal_info_status(&self) -> i32 {
54        match self {
55            ExitStatus::Exit(status) => *status as i32,
56            ExitStatus::Kill(siginfo)
57            | ExitStatus::CoreDump(siginfo)
58            | ExitStatus::Continue(siginfo, _)
59            | ExitStatus::Stop(siginfo, _) => siginfo.signal.number() as i32,
60        }
61    }
62}
63
64impl Default for ExitStatus {
65    fn default() -> Self {
66        Self::Exit(0)
67    }
68}