refactor: migrate uucore process.rs from nix to rustix

Replace nix process functions with rustix equivalents:
- geteuid/getegid/getuid/getgid/getpid/getpgrp/getsid -> rustix::process
- kill/test_kill -> rustix::process::kill_process/test_kill_process
- Signal::try_from -> signal_from_raw helper using from_raw_unchecked
- SigHandler for send_signal_group -> csignal wrapper

The getsid return type changes from Result<pid_t, Errno> to
io::Result<pid_t>, which is more idiomatic.
This commit is contained in:
Sylvestre Ledru
2026-03-28 11:13:24 +01:00
parent 9949abb827
commit 1f91dbacd6
+43 -34
View File
@@ -8,10 +8,7 @@
// spell-checker:ignore pgrep pwait snice getpgrp
use libc::{gid_t, pid_t, uid_t};
#[cfg(not(target_os = "redox"))]
use nix::errno::Errno;
use nix::sys::signal::{self as nix_signal, SigHandler, Signal};
use nix::unistd::Pid;
use rustix::process::{self as rprocess, Pid, Signal};
use std::io;
use std::process::Child;
use std::process::ExitStatus;
@@ -20,35 +17,47 @@ use std::sync::atomic::AtomicBool;
use std::thread;
use std::time::{Duration, Instant};
use crate::signals::csignal;
/// Convert a raw signal number to a `Signal`, returning an error for invalid values.
fn signal_from_raw(sig: i32) -> io::Result<Signal> {
if sig > 0 {
// SAFETY: we've checked the value is positive; the kernel will reject
// truly invalid signal numbers.
Ok(unsafe { Signal::from_raw_unchecked(sig) })
} else {
Err(io::Error::from_raw_os_error(libc::EINVAL))
}
}
/// `geteuid()` returns the effective user ID of the calling process.
pub fn geteuid() -> uid_t {
nix::unistd::geteuid().as_raw()
rprocess::geteuid().as_raw()
}
/// `getpgrp()` returns the process group ID of the calling process.
/// It is a trivial wrapper over nix::unistd::getpgrp.
pub fn getpgrp() -> pid_t {
nix::unistd::getpgrp().as_raw()
rprocess::getpgrp().as_raw_nonzero().get()
}
/// `getegid()` returns the effective group ID of the calling process.
pub fn getegid() -> gid_t {
nix::unistd::getegid().as_raw()
rprocess::getegid().as_raw()
}
/// `getgid()` returns the real group ID of the calling process.
pub fn getgid() -> gid_t {
nix::unistd::getgid().as_raw()
rprocess::getgid().as_raw()
}
/// `getuid()` returns the real user ID of the calling process.
pub fn getuid() -> uid_t {
nix::unistd::getuid().as_raw()
rprocess::getuid().as_raw()
}
/// `getpid()` returns the pid of the calling process.
pub fn getpid() -> pid_t {
nix::unistd::getpid().as_raw()
rprocess::getpid().as_raw_nonzero().get()
}
/// `getsid()` returns the session ID of the process with process ID pid.
@@ -57,22 +66,23 @@ pub fn getpid() -> pid_t {
///
/// # Error
///
/// - [Errno::EPERM] A process with process ID pid exists, but it is not in the same session as the calling process, and the implementation considers this an error.
/// - [Errno::ESRCH] No process with process ID pid was found.
///
/// - EPERM: A process with process ID pid exists, but it is not in the same session as the calling process, and the implementation considers this an error.
/// - ESRCH: No process with process ID pid was found.
///
/// # Platform
///
/// This function only support standard POSIX implementation platform,
/// so some system such as redox doesn't supported.
#[cfg(not(target_os = "redox"))]
pub fn getsid(pid: i32) -> Result<pid_t, Errno> {
pub fn getsid(pid: i32) -> io::Result<pid_t> {
let pid = if pid == 0 {
None
} else {
Some(Pid::from_raw(pid))
Some(Pid::from_raw(pid).ok_or_else(|| io::Error::from_raw_os_error(libc::EINVAL))?)
};
nix::unistd::getsid(pid).map(Pid::as_raw)
rprocess::getsid(pid)
.map(|p| p.as_raw_nonzero().get())
.map_err(Into::into)
}
/// Missing methods for Child objects
@@ -97,15 +107,15 @@ pub trait ChildExt {
impl ChildExt for Child {
fn send_signal(&mut self, signal: usize) -> io::Result<()> {
let pid = Pid::from_raw(self.id() as pid_t);
let result = if signal == 0 {
nix_signal::kill(pid, None)
let pid = Pid::from_raw(self.id() as pid_t)
.ok_or_else(|| io::Error::from_raw_os_error(libc::EINVAL))?;
if signal == 0 {
rprocess::test_kill_process(pid)?;
} else {
let signal = Signal::try_from(signal as i32)
.map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?;
nix_signal::kill(pid, Some(signal))
};
result.map_err(|e| io::Error::from_raw_os_error(e as i32))
let sig = signal_from_raw(signal as i32)?;
rprocess::kill_process(pid, sig)?;
}
Ok(())
}
fn send_signal_group(&mut self, signal: usize) -> io::Result<()> {
@@ -118,20 +128,19 @@ impl ChildExt for Child {
// Signal 0 is special - it just checks if process exists, doesn't send anything.
// No need to manipulate signal handlers for it.
if signal == 0 {
return nix_signal::kill(Pid::from_raw(0), None)
.map_err(|e| io::Error::from_raw_os_error(e as i32));
return rprocess::test_kill_current_process_group().map_err(Into::into);
}
let signal = Signal::try_from(signal as i32)
.map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?;
let sig = signal_from_raw(signal as i32)?;
// Ignore the signal temporarily so we don't receive it ourselves.
let old_handler = unsafe { nix_signal::signal(signal, SigHandler::SigIgn) }
.map_err(|e| io::Error::from_raw_os_error(e as i32))?;
let result = nix_signal::kill(Pid::from_raw(0), Some(signal));
let old_handler = unsafe {
csignal::set_signal_handler(signal as libc::c_int, csignal::SigHandler::SigIgn)
}?;
let result = rprocess::kill_current_process_group(sig);
// Restore the old handler
let _ = unsafe { nix_signal::signal(signal, old_handler) };
result.map_err(|e| io::Error::from_raw_os_error(e as i32))
let _ = unsafe { csignal::set_signal_handler(signal as libc::c_int, old_handler) };
result.map_err(Into::into)
}
fn wait_or_timeout(