pub(super) fn terminate(pid: u32, expected_start: &str) -> anyhow::Result<()> {
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd};
let fd = unsafe { libc::syscall(libc::SYS_pidfd_open, pid, 0) };
if fd < 0 {
return Err(std::io::Error::last_os_error().into());
}
let fd = unsafe { OwnedFd::from_raw_fd(fd as i32) };
anyhow::ensure!(
start(pid).as_deref() == Some(expected_start),
"Command died or its process identity changed; no signal sent"
);
let sent = unsafe {
libc::syscall(
libc::SYS_pidfd_send_signal,
fd.as_raw_fd(),
libc::SIGTERM,
std::ptr::null::<libc::siginfo_t>(),
0,
)
};
if sent < 0 {
return Err(std::io::Error::last_os_error().into());
}
Ok(())
}
pub(super) fn start(pid: u32) -> Option<String> {
let stat = std::fs::read_to_string(format!("/proc/{pid}/stat")).ok()?;
let (_, fields) = stat.rsplit_once(") ")?;
let fields: Vec<_> = fields.split_whitespace().collect();
if matches!(*fields.first()?, "Z" | "X") {
return None;
}
let ticks = fields.get(19)?; let boot = std::fs::read_to_string("/proc/sys/kernel/random/boot_id").ok()?;
Some(format!("{}:{ticks}", boot.trim()))
}