The project is in a healthy, maintained state
File locks using flock and PID file locks with stale detection for coordinating between processes. Timeout support and automatic cleanup.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

philiprehberger-lock_kit

Tests Gem Version Last updated

File-based and PID locking for process coordination with stale lock detection, read-write locks, and lock owner identification.

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem 'philiprehberger-lock_kit'

Or install directly:

gem install philiprehberger-lock_kit

Usage

require 'philiprehberger/lock_kit'

Philiprehberger::LockKit.with_file_lock('/tmp/my.lock') do
  # exclusive work here
end

File Locking with Timeout

Philiprehberger::LockKit.with_file_lock('/tmp/my.lock', timeout: 5) do
  # waits up to 5 seconds for the lock
end

PID File Locking

Philiprehberger::LockKit.with_pid_lock('my_worker') do
  # only one process with this name can run at a time
end

Read-Write Locks

# Multiple readers can hold the lock concurrently
Philiprehberger::LockKit.with_read_lock('/tmp/data.lock', timeout: 5) do
  # read shared data
end

# Write lock is exclusive — no readers or other writers allowed
Philiprehberger::LockKit.with_write_lock('/tmp/data.lock', timeout: 5) do
  # write shared data
end

Automatic Stale Lock Cleanup

Philiprehberger::LockKit.with_file_lock('/tmp/my.lock', auto_cleanup: true) do
  # automatically removes stale locks from dead processes
end

Philiprehberger::LockKit.with_pid_lock('my_worker', auto_cleanup: true) do
  # same for PID locks
end

Lock Owner Identification

info = Philiprehberger::LockKit.owner('/tmp/my.lock')
# => { pid: 12345, hostname: 'web-01', acquired_at: 2026-03-28 12:00:00 +0000 }

Lock Waiting with Callbacks

Philiprehberger::LockKit.with_file_lock('/tmp/my.lock', timeout: 10, on_wait: ->(elapsed) { puts "Waiting #{elapsed}s..." }) do
  # callback fires every 0.5s while waiting
end

Force Break Lock

# Break stale locks only (raises if held by a live process)
Philiprehberger::LockKit.break!('/tmp/my.lock')
# => { broken: true, previous_owner: { pid: 12345, hostname: 'web-01', acquired_at: ... } }

# Force break any lock regardless of status
Philiprehberger::LockKit.break!('/tmp/my.lock', force: true)

Manual File Lock

lock = Philiprehberger::LockKit::FileLock.new('/tmp/my.lock')
lock.acquire(timeout: 10)
# ... do work ...
lock.release

Manual PID Lock

lock = Philiprehberger::LockKit::PidLock.new('my_worker', dir: '/var/run')
lock.acquire
# ... do work ...
lock.release

Checking Lock Status

Philiprehberger::LockKit.locked?('/tmp/my.lock')      # => true/false
Philiprehberger::LockKit.stale?('/tmp/my_worker.pid')  # => true/false

API

LockKit

Method Description
.with_file_lock(path, timeout: nil, auto_cleanup: false, on_wait: nil) { } Execute block with exclusive file lock
.with_pid_lock(name, dir: Dir.tmpdir, auto_cleanup: false) { } Execute block with PID file lock
.with_read_lock(path, timeout: nil) { } Execute block with shared read lock
.with_write_lock(path, timeout: nil) { } Execute block with exclusive write lock
.locked?(path) Check if a file is currently locked
.stale?(pid_file) Check if a PID file references a dead process
.owner(path) Get lock owner metadata (pid, hostname, acquired_at)
.break!(path, force: false) Break a lock (stale only by default, any with force)

LockKit::FileLock

Method Description
.new(path) Create a file lock instance
#acquire(timeout: nil, auto_cleanup: false, on_wait: nil) Acquire exclusive lock with optional timeout, cleanup, and wait callback
#release Release the lock and close the file handle
#locked? Check if the file is currently locked
#owner Get lock owner metadata

LockKit::PidLock

Method Description
.new(name, dir: Dir.tmpdir) Create a PID lock instance
#acquire(auto_cleanup: false) Acquire PID lock, raises if held by a living process
#release Release lock and remove PID file
#locked? Check if lock is held by a living process
#stale? Check if PID file references a dead process
#owner Get lock owner metadata

LockKit::ReadWriteLock

Method Description
.new(path) Create a read-write lock instance
#acquire_read(timeout: nil) Acquire shared read lock
#release_read Release the read lock
#acquire_write(timeout: nil) Acquire exclusive write lock
#release_write Release the write lock
#reader_count Get current number of active readers

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT