feat(xy): exclusive pidfile guard

This commit is contained in:
2026-05-25 11:48:38 +02:00
parent 58c44e0b48
commit 49c006df10
+46
View File
@@ -0,0 +1,46 @@
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::os::unix::fs::OpenOptionsExt;
use std::path::{Path, PathBuf};
#[derive(Debug)]
pub struct PidFile {
path: PathBuf,
_file: File,
}
impl PidFile {
pub fn acquire(path: &Path) -> std::io::Result<Self> {
let mut f = OpenOptions::new()
.write(true).create_new(true).mode(0o600).open(path)?;
writeln!(f, "{}", std::process::id())?;
Ok(Self { path: path.to_path_buf(), _file: f })
}
}
impl Drop for PidFile {
fn drop(&mut self) { let _ = std::fs::remove_file(&self.path); }
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn acquire_then_second_fails() {
let dir = tempdir().unwrap();
let p = dir.path().join("x.pid");
let _g = PidFile::acquire(&p).unwrap();
let err = PidFile::acquire(&p).unwrap_err();
assert_eq!(err.kind(), std::io::ErrorKind::AlreadyExists);
}
#[test]
fn drop_removes_file() {
let dir = tempdir().unwrap();
let p = dir.path().join("x.pid");
{ let _g = PidFile::acquire(&p).unwrap(); assert!(p.exists()); }
assert!(!p.exists());
}
}