Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rustix::process::exit to terminate processes #1133

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/backend/libc/process/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,3 +742,14 @@ pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result<usize> {

unsafe { ret_usize(c::getgroups(len, buf.as_mut_ptr().cast()) as isize) }
}

#[inline]
pub(crate) fn _exit(status: i32) -> ! {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifiers with leading underscores have a special meaning in Rust, so I suggest we rename this internal function to immediate_exit as well.

unsafe {
libc::_exit(status);
}
#[allow(unreachable_code)]
{
unreachable!("_exit failed to exit the process")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can leave these four lines out. The _exit function already has a return type of ! so Rust is already assuming it won't return.

}
2 changes: 1 addition & 1 deletion src/backend/linux_raw/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ macro_rules! syscall_readonly {
}

/// Like `syscall`, but indicates that the syscall does not return.
#[cfg(feature = "runtime")]
#[cfg(any(feature = "runtime", feature = "process"))]
macro_rules! syscall_noreturn {
($nr:ident, $a0:expr) => {
$crate::backend::arch::choose::syscall1_noreturn(
Expand Down
11 changes: 11 additions & 0 deletions src/backend/linux_raw/process/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,3 +620,14 @@ pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result<usize> {
))
}
}

#[inline]
pub(crate) fn _exit(status: i32) -> ! {
unsafe {
syscall_noreturn!(__NR_exit_group, c_int(status));
};
#[allow(unreachable_code)]
{
unreachable!("_exit failed to exit the process")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we can leave these four lines out because the noreturn in the inline asm is already telling Rust that the inline asm won't return.

}
35 changes: 29 additions & 6 deletions src/process/exit.rs
Original file line number Diff line number Diff line change
@@ -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`].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function is named immediate_exit now. And it's a minor nit, but please put std::process::exit first, as that's still the main function here.

///
/// # References
/// - [POSIX]
Expand All @@ -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`].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as for EXIT_SUCCESS.

///
/// # References
/// - [POSIX]
Expand All @@ -34,3 +30,30 @@ 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
sunfishcode marked this conversation as resolved.
Show resolved Hide resolved
/// the POSIX/C `_Exit` and `_exit` functions.
///
/// Notably, this function does:
/// - *Not* flush any buffers, such as Rust or C standard output or files.
/// - *Not* call any destructors, neither in the form of stack unwinding, nor
/// any global destructors.
/// - *Not* call functions registered with [`atexit`] or [`at_quick_exit`]
///
/// In general, most code should call [`std::process::exit`] instead, if it is
/// available.
///
/// # 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
/// [`atexit`]: https://www.man7.org/linux/man-pages/man3/atexit.3.html
/// [`at_quick_exit`]: https://en.cppreference.com/w/c/program/at_quick_exit
#[doc(alias = "_exit")]
#[inline]
pub fn immediate_exit(status: i32) -> ! {
backend::process::syscalls::_exit(status);
}
Loading