TIL: Using File Locking for Exclusivity in Ruby
Two TILs in one, how to use native file locking to prevent more than one process running at the same time.
Here I'll grab a file and create an exclusive lock.
file = File.new('process.lock')
file.flock(File::LOCK_EX)
# do something exclusively
file.flock(File::LOCK_UN)
If two process are running concurrently, the first one to hit line 2 gets an exclusive lock. The second process waits until it can get a lock. The lock is released at line 4 (which really should have an ensure
to make sure it gets executed).
What happens if I want to fail fast?
file = File.new('process.lock')
file.flock(File::LOCK_EX | File::LOCK_NB) or abort 'Already running'
The LOCK_NB
is a flag to indicate non-blocking. The second process will fail to get the lock but then fail-fast.
The __DATA__
File
Imagine I had a file like this:
DATA.flock(File::LOCK_EX | File::LOCK_NB) or abort 'Already running'
__END__
Sentinel for locking
After a __END__
(that two underscores before and after the END
) the content become available via the special DATA
variable which is an IO
like object. With this trick, I can have exclusive locks without needing a special lock file.
Member discussion