summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Hummer <paul@eventuallyanyway.com>2018-06-04 15:19:13 -0600
committerPaul Hummer <paul@eventuallyanyway.com>2018-06-04 15:19:13 -0600
commite8577a46e19a04ee2d3469333e6b1b090106aef8 (patch)
treec9c1b1b06d6403c33a0ac20c04f5d00011b67c05
parent84a67f7b0cee4243d1b1f24f3c59d2aa5b4259ea (diff)
Add support for removing stale pid files.
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
-rw-r--r--Cargo.toml1
-rw-r--r--src/lib.rs36
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::<i32>() {
+ 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,