pub fn is_pid_alive(pid: u32) -> bool {
platform::is_pid_alive_impl(pid)
}
pub fn parent_pid() -> Option<u32> {
platform::parent_pid_impl()
}
#[cfg(unix)]
mod platform {
pub fn is_pid_alive_impl(pid: u32) -> bool {
if pid == 0 {
return false;
}
let rc = unsafe { libc::kill(pid as libc::pid_t, 0) };
if rc == 0 {
return true;
}
std::io::Error::last_os_error().raw_os_error() == Some(libc::EPERM)
}
pub fn parent_pid_impl() -> Option<u32> {
let ppid = unsafe { libc::getppid() };
if ppid > 0 { Some(ppid as u32) } else { None }
}
}
#[cfg(windows)]
mod platform {
use std::ptr;
const PROCESS_QUERY_LIMITED_INFORMATION: u32 = 0x1000;
const STILL_ACTIVE: u32 = 259;
unsafe extern "system" {
fn OpenProcess(
desired_access: u32,
inherit_handles: i32,
process_id: u32,
) -> *mut core::ffi::c_void;
fn CloseHandle(handle: *mut core::ffi::c_void) -> i32;
fn GetExitCodeProcess(handle: *mut core::ffi::c_void, exit_code: *mut u32) -> i32;
}
pub fn is_pid_alive_impl(pid: u32) -> bool {
if pid == 0 {
return false;
}
unsafe {
let handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
if handle.is_null() || handle == ptr::null_mut() {
return false;
}
let mut exit_code: u32 = 0;
let success = GetExitCodeProcess(handle, &mut exit_code);
CloseHandle(handle);
success != 0 && exit_code == STILL_ACTIVE
}
}
pub fn parent_pid_impl() -> Option<u32> {
None
}
}
#[cfg(not(any(unix, windows)))]
mod platform {
pub fn is_pid_alive_impl(_pid: u32) -> bool {
false
}
pub fn parent_pid_impl() -> Option<u32> {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn current_process_is_alive() {
let pid = std::process::id();
assert!(
is_pid_alive(pid),
"current process (PID {pid}) must be detected as alive"
);
}
#[test]
fn nonexistent_pid_is_dead() {
let dead_pid = (i32::MAX - 1) as u32;
assert!(
!is_pid_alive(dead_pid),
"PID {dead_pid} should not be alive"
);
}
#[test]
fn pid_zero_is_not_alive() {
assert!(!is_pid_alive(0), "PID 0 should not be considered alive");
}
#[cfg(unix)]
#[test]
fn parent_pid_is_available_on_unix() {
assert!(
parent_pid().is_some(),
"parent_pid should be present on unix platforms"
);
}
}