diff --git a/src/backend/libc/process/syscalls.rs b/src/backend/libc/process/syscalls.rs index efb5a77f0..e75d29145 100644 --- a/src/backend/libc/process/syscalls.rs +++ b/src/backend/libc/process/syscalls.rs @@ -742,3 +742,12 @@ pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result { unsafe { ret_usize(c::getgroups(len, buf.as_mut_ptr().cast()) as isize) } } + +#[cfg(not(target_os = "wasi"))] +#[inline] +pub(crate) fn _exit(status: i32) -> ! { + unsafe { + libc::_exit(status); + } + unreachable!("_exit failed to exit the process"); +} diff --git a/src/backend/linux_raw/process/syscalls.rs b/src/backend/linux_raw/process/syscalls.rs index d562aab33..2438cdec0 100644 --- a/src/backend/linux_raw/process/syscalls.rs +++ b/src/backend/linux_raw/process/syscalls.rs @@ -620,3 +620,10 @@ pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result { )) } } + +#[inline] +pub(crate) fn _exit(status: i32) -> ! { + unsafe { + syscall_noreturn!(__NR_exit_group, c_int(status)); + }; +} diff --git a/src/process/exit.rs b/src/process/exit.rs index 95b78c4a1..dfcef25c5 100644 --- a/src/process/exit.rs +++ b/src/process/exit.rs @@ -1,8 +1,6 @@ use crate::backend; -/// `EXIT_SUCCESS` for use with [`exit`]. -/// -/// [`exit`]: std::process::exit +/// `EXIT_SUCCESS` for use with [`exit`] or [`std::process::exit`]. /// /// # References /// - [POSIX] @@ -12,9 +10,7 @@ use crate::backend; /// [Linux]: https://man7.org/linux/man-pages/man3/exit.3.html pub const EXIT_SUCCESS: i32 = backend::c::EXIT_SUCCESS; -/// `EXIT_FAILURE` for use with [`exit`]. -/// -/// [`exit`]: std::process::exit +/// `EXIT_FAILURE` for use with [`exit`] or [`std::process::exit`]. /// /// # References /// - [POSIX] @@ -34,3 +30,18 @@ pub const EXIT_FAILURE: i32 = backend::c::EXIT_FAILURE; /// [`Signal::Abort`]: crate::process::Signal::Abort #[cfg(not(any(target_os = "espidf", target_os = "wasi")))] pub const EXIT_SIGNALED_SIGABRT: i32 = backend::c::EXIT_SIGNALED_SIGABRT; + +/// Immediately exits the process. Exiting via this function does not unwind the +/// stack and does not call any further user code. This behavior is similar to +/// the POSIX/C `_Exit` and `_exit` functions. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html +/// [Linux]: https://www.man7.org/linux/man-pages/man2/exit.2.html +#[inline] +pub fn exit(status: i32) -> ! { + backend::process::syscalls::_exit(status); +}