#pid-file #server #file-lock #locking

pidlock

A library for using pidfiles as resource locks

9 releases

Uses new Rust 2024

0.2.2 Oct 17, 2025
0.2.1 Sep 7, 2025
0.1.6 Dec 16, 2023
0.1.4 Jan 20, 2021
0.1.1 May 19, 2018

#219 in Filesystem

Download history 232/week @ 2025-08-13 216/week @ 2025-08-20 238/week @ 2025-08-27 506/week @ 2025-09-03 209/week @ 2025-09-10 83/week @ 2025-09-17 52/week @ 2025-09-24 70/week @ 2025-10-01 62/week @ 2025-10-08 189/week @ 2025-10-15 86/week @ 2025-10-22 39/week @ 2025-10-29 35/week @ 2025-11-05 195/week @ 2025-11-12 103/week @ 2025-11-19 44/week @ 2025-11-26

384 downloads per month
Used in 13 crates (via amdgpu)

MIT license

74KB
2K SLoC

pidlock

A library for creating and managing PID-based file locks, providing a simple and reliable way to ensure only one instance of a program runs at a time.

Crates.io Documentation CI

Features

  • Cross-platform: Works on Unix-like systems and Windows
  • Stale lock detection: Automatically detects and cleans up locks from dead processes
  • Path validation: Ensures lock file paths are valid across platforms
  • Safe cleanup: Automatically releases locks when the Pidlock is dropped
  • Comprehensive error handling: Detailed error types for different failure scenarios

Quick Start

Add this to your Cargo.toml:

[dependencies]
pidlock = "0.2"

Basic Usage

use pidlock::Pidlock;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a new lock
    let mut lock = Pidlock::new_validated("/run/lock/my_app.pid")?;

    // Try to acquire the lock
    match lock.acquire() {
        Ok(()) => {
            println!("Lock acquired successfully!");
            
            // Do your work here...
            
            // Explicitly release the lock (optional - it's auto-released on drop)
            lock.release()?;
        }
        Err(pidlock::PidlockError::LockExists) => {
            println!("Another instance is already running");
            std::process::exit(1);
        }
        Err(e) => {
            eprintln!("Failed to acquire lock: {}", e);
            std::process::exit(1);
        }
    }
    
    Ok(())
}

Advanced Usage

Checking Lock Status

use pidlock::Pidlock;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let lock = Pidlock::new_validated("/run/lock/my_app.pid")?;

    // Check if a lock file exists
    if lock.exists() {
        // Check if the lock is held by an active process
        match lock.is_active()? {
            true => println!("Lock is held by an active process"),
            false => println!("Lock file exists but process is dead (stale lock)"),
        }
    } else {
        println!("No lock file exists");
    }
    
    Ok(())
}

Error Handling

use pidlock::{Pidlock, PidlockError, InvalidPathError};

fn main() {
    let result = Pidlock::new_validated("invalid<path>");
    match result {
        Ok(_) => println!("Path is valid"),
        Err(PidlockError::InvalidPath(InvalidPathError::ProblematicCharacter { character, filename })) => {
            println!("Invalid character '{}' in filename: {}", character, filename);
        }
        Err(e) => println!("Other error: {}", e),
    }
}

Safe Cleanup with RAII

use pidlock::Pidlock;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    {
        let mut lock = Pidlock::new_validated("/run/lock/my_app.pid")?;
        lock.acquire()?;
        
        // Do work here...
        // Lock is automatically released when it goes out of scope
    }
    
    // Lock file is now cleaned up
    Ok(())
}

Migration from 0.1.x

If you're upgrading from version 0.1.x:

  • Replace Pidlock::new() with Pidlock::new_validated() for better error handling
  • Handle the additional Result type returned by new_validated()
  • Consider the improved error types for more specific error handling
// Old (0.1.x)
let mut lock = pidlock::Pidlock::new("/path/to/pidfile.pid");

// New (0.2.x)
let mut lock = pidlock::Pidlock::new_validated("/path/to/pidfile.pid")?;

Platform Considerations

  • Unix/Linux: Uses POSIX signals for process detection, respects umask for permissions
  • Windows: Uses Win32 APIs for process detection, handles reserved filenames
  • File permissions: Lock files are created with restrictive permissions (600 on Unix)
  • Path validation: Automatically validates paths for cross-platform compatibility

Safety

This library uses unsafe code for platform-specific process detection, but all unsafe operations are carefully validated and documented. The library ensures that:

  • PID values are validated before use in system calls
  • Windows handles are properly managed and cleaned up
  • Unix signals are used safely without affecting target processes

License

pidlock is licensed under the MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

Dependencies

~2–31MB
~510K SLoC