use std::path::PathBuf;
use super::scoping::session_dir;
fn pid_path(session_key: &str) -> PathBuf {
session_dir().join(format!("{session_key}.pid"))
}
pub fn write_pid(session_key: &str) -> std::io::Result<()> {
let path = pid_path(session_key);
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
std::fs::write(&path, std::process::id().to_string())
}
pub fn remove_pid(session_key: &str) -> std::io::Result<()> {
let path = pid_path(session_key);
match std::fs::remove_file(&path) {
Ok(()) => Ok(()),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(e) => Err(e),
}
}
pub fn read_pid(session_key: &str) -> Option<u32> {
let path = pid_path(session_key);
let contents = std::fs::read_to_string(&path).ok()?;
let pid: u32 = contents.trim().parse().ok()?;
if is_process_alive(pid) {
Some(pid)
} else {
let _ = std::fs::remove_file(&path);
None
}
}
fn is_process_alive(pid: u32) -> bool {
let ret = unsafe { libc::kill(pid as libc::pid_t, 0) };
if ret == 0 {
return true;
}
std::io::Error::last_os_error().raw_os_error() == Some(libc::EPERM)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn current_process_is_alive() {
assert!(is_process_alive(std::process::id()));
}
#[test]
fn bogus_pid_is_not_alive() {
assert!(!is_process_alive(4_000_000));
}
}