feat(xy): exclusive pidfile guard
This commit is contained in:
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user