Tuesday, July 8, 2014

file locking using a context manager (with statement) in python

I needed a quick locking mechanism to prevent my daemons from stepping over each other. To have a sane daemon startup (and prevent multiple daemon spawns), we need to ensure that we have an exclusive lock before starting the program.  Googling around didn't lead to show any context managers that actually use the flock syscalls.

So here goes my attempt that seems to work:

import fcntl
class FileLock:
def __init__(self, filename, lock_type):
self.fh = open(filename, "a")
self.lock_type = lock_type
def __enter__(self):
print "Acquiring lock"
fcntl.flock(self.fh.fileno(), self.lock_type)
def __exit__(self, type, value, tb):
print "Releasing lock"
fcntl.flock(self.fh.fileno(), fcntl.LOCK_UN)
self.fh.close()
def main():
import os
import time
with FileLock("/tmp/some_lock_file", fcntl.LOCK_EX):
print "Start: %s" % time.ctime()
print "PID: %s" % os.getpid()
time.sleep(5)
print "Finish: %s" % time.ctime()
if __name__ == '__main__':
main()
view raw flock.py hosted with ❤ by GitHub
Spinning off some python processes that utilise this context manager shows serialisation taking place:
Starting process 1
Starting process 2
Starting process 3
Starting process 4
Starting process 5
Acquiring lock
Start: Tue Jul 8 11:51:22 2014
Acquiring lock
Acquiring lock
PID: 826
Acquiring lock
Acquiring lock
Finish: Tue Jul 8 11:51:27 2014
Releasing lock
Start: Tue Jul 8 11:51:27 2014
PID: 825
Finish: Tue Jul 8 11:51:32 2014
Releasing lock
Start: Tue Jul 8 11:51:32 2014
PID: 824
Finish: Tue Jul 8 11:51:37 2014
Releasing lock
Start: Tue Jul 8 11:51:37 2014
PID: 823
Finish: Tue Jul 8 11:51:42 2014
Releasing lock
Start: Tue Jul 8 11:51:42 2014
PID: 822
Finish: Tue Jul 8 11:51:47 2014
Releasing lock
And here's the output of lsof showing locking for the processes spun off above:
Tue Jul 8 11:51:18 UTC 2014
Tue Jul 8 11:51:20 UTC 2014
Tue Jul 8 11:51:22 UTC 2014
Tue Jul 8 11:51:24 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 824 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 825 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 826 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:26 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 824 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 825 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 826 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:28 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 824 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 825 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:30 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 824 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 825 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:32 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 824 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 825 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:34 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 824 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:36 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 824 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:38 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:40 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:42 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3w REG 254,0 0 1973047 /tmp/some_lock_file
python 823 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:44 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:46 UTC 2014
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 822 vagrant 3wW REG 254,0 0 1973047 /tmp/some_lock_file
Tue Jul 8 11:51:48 UTC 2014
Tue Jul 8 11:51:50 UTC 2014
view raw lsof.output hosted with ❤ by GitHub

No comments:

Post a Comment