104 lines
3.0 KiB
Rust
104 lines
3.0 KiB
Rust
//! Data structures for process management
|
|
|
|
use core::num::NonZeroI32;
|
|
|
|
use crate::{arch::SavedFrame, io::RawFd, primitive_enum};
|
|
|
|
/// Code signalled by a process when it finishes or is terminated by a signal
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
#[repr(C)]
|
|
pub enum ExitCode {
|
|
/// Process exited normally, either with an error or with a 0
|
|
Exited(i32),
|
|
/// Process was killed by a signal
|
|
BySignal(Signal),
|
|
}
|
|
|
|
/// Defines an optional argument for controlling process creation
|
|
#[derive(Debug)]
|
|
pub enum SpawnOption {
|
|
/// Indicates a new process should inherit a file descriptor from its creator
|
|
InheritFile {
|
|
/// FD on the creator side
|
|
source: RawFd,
|
|
/// What FD number should be used in the child
|
|
child: RawFd,
|
|
},
|
|
}
|
|
|
|
primitive_enum! {
|
|
#[doc = "Defines signal numbers sent to processes"]
|
|
pub enum Signal: u32 {
|
|
#[doc = "Process has tried to perform an illegal memory operation"]
|
|
MemoryAccessViolation = 1,
|
|
#[doc = "Process has hit a breakpoint or was aborted"]
|
|
Aborted = 2,
|
|
#[doc = "Process was killed"]
|
|
Killed = 3,
|
|
#[doc = "Process was interrupted"]
|
|
Interrupted = 4,
|
|
}
|
|
}
|
|
|
|
/// Data provided by the kernel to signal entry function
|
|
#[derive(Clone, Debug)]
|
|
#[repr(C)]
|
|
pub struct SignalEntryData {
|
|
/// Which signal was issued
|
|
pub signal: Signal,
|
|
/// Saved frame of the context that was interrupted
|
|
pub frame: SavedFrame,
|
|
}
|
|
|
|
/// Controls how processes are created
|
|
#[derive(Clone, Debug)]
|
|
#[repr(C)]
|
|
pub struct SpawnOptions<'a> {
|
|
/// Creator-relative path to the binary to execute
|
|
pub program: &'a str,
|
|
/// Arguments to the child process
|
|
pub arguments: &'a [&'a str],
|
|
/// Optional arguments to specify details of the creation
|
|
pub optional: &'a [SpawnOption],
|
|
}
|
|
|
|
impl ExitCode {
|
|
/// Returned when a process has exited successfully
|
|
pub const SUCCESS: Self = Self::Exited(0);
|
|
|
|
/// Returns `true` if this ExitCode signals a successful exit
|
|
pub const fn is_success(self) -> bool {
|
|
matches!(self, Self::Exited(0))
|
|
}
|
|
|
|
/// Returns [Some] if the process exited with an error or was killed by a signal
|
|
pub fn as_failure(self) -> Option<NonZeroI32> {
|
|
match self {
|
|
Self::Exited(0) => None,
|
|
Self::Exited(n) => Some(unsafe { NonZeroI32::new_unchecked(n) }),
|
|
Self::BySignal(sig) => {
|
|
Some(unsafe { NonZeroI32::new_unchecked(u32::from(sig) as i32) })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<i32> for ExitCode {
|
|
fn from(value: i32) -> Self {
|
|
match value {
|
|
-255..=255 => Self::Exited(value),
|
|
10000.. => Self::BySignal(Signal::try_from(value as u32 - 10000).unwrap()),
|
|
_ => todo!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ExitCode> for i32 {
|
|
fn from(value: ExitCode) -> Self {
|
|
match value {
|
|
ExitCode::BySignal(signal) => 10000 + u32::from(signal) as i32,
|
|
ExitCode::Exited(value) => value,
|
|
}
|
|
}
|
|
}
|