1 min read

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

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.