From e8577a46e19a04ee2d3469333e6b1b090106aef8 Mon Sep 17 00:00:00 2001 From: Paul Hummer Date: Mon, 4 Jun 2018 15:19:13 -0600 Subject: Add support for removing stale pid files. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the pid refers to a process that no longer exists, `Pidlock.acquire` will remove the stale pid file. ♬ : Coheed and Cambria / The Dark Sentencer --- Cargo.toml | 1 + src/lib.rs | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c8267b8..d7b8797 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ include = [ [dependencies] libc = "0.2.40" +log = "0.4.1" [badges] travis-ci = { repository = "rockstar/pidlock" } diff --git a/src/lib.rs b/src/lib.rs index dd5bd9e..b9138b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ extern crate libc; +#[macro_use] +extern crate log; use std::fs; -use std::io::Write; +use std::io::{Read, Write}; #[derive(Debug, PartialEq)] pub enum PidlockError { @@ -22,6 +24,16 @@ fn getpid() -> u32 { unsafe { libc::getpid() as u32 } } +fn process_exists(pid: i32) -> bool { + // From the POSIX standard: If sig is 0 (the null signal), error checking + // is performed but no signal is actually sent. The null signal can be + // used to check the validity of pid. + unsafe { + let result = libc::kill(pid, 0); + result == 0 + } +} + pub struct Pidlock { pid: u32, path: String, @@ -37,6 +49,26 @@ impl Pidlock { } } + fn check_stale(&self) { + match fs::OpenOptions::new().read(true).open(self.path.clone()) { + Ok(mut file) => { + let mut contents = String::new(); + file.read_to_string(&mut contents).unwrap(); + + match contents.trim().parse::() { + Ok(pid) => { + if !process_exists(pid) { + warn!("Removing stale pid file at {}", self.path); + fs::remove_file(&self.path).unwrap(); + } + } + Err(_) => fs::remove_file(&self.path).unwrap(), + } + } + Err(_) => {} + }; + } + pub fn acquire(&mut self) -> PidlockResult { match self.state { PidlockState::New => {} @@ -44,11 +76,11 @@ impl Pidlock { return Err(PidlockError::InvalidState); } } + self.check_stale(); let mut file = match fs::OpenOptions::new() .create_new(true) .write(true) - .read(true) .open(self.path.clone()) { Ok(file) => file, -- cgit v1.2.3