I have a Thread
-extending class that is supposed to run only one instance at a time (cross-process). In order to achieve that, I'm trying to use a file lock. Here are bits of my code:
class Scanner(Thread):
def __init__(self, path):
Thread.__init__(self)
self.lock_file = open(os.path.join(config.BASEDIR, "scanner.lock"), 'r+')
fcntl.lockf(self.lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
# Stuff omitted
def run(self):
logging.info("Starting scan on %s" % self.path)
# More stuff omitted
fcntl.lockf(self.lock_file, fcntl.LOCK_UN)
I was expecting the lockf
call to throw an exception if a Scanner
thread was already running and not initialize the object at all. However, I can see this in the terminal:
INFO:root:Starting scan on /home/felix/Music
INFO:root:Starting scan on /home/felix/Music
INFO:root:Scan finished
INFO:root:Scan finished
Which suggests that two Scanner
threads are running at the same time, no exception thrown. I'm sure I'm missing something really basic here, but I can't seem to figure out wha开发者_开发百科t that is. Can anyone help?
Found the solution myself in the end. It was to use fcntl.flock()
instead of fcntl.lockf()
, with the exact same parameters. Not sure why that made a difference.
You're opening the lock file using r+
which is erasing the previous file and creating a new one. Each thread is locking a different file.
Use w
or r+a
Along with using flock, I had to also open the file like so :
fd = os.open(lockfile, os.O_CREAT | os.O_TRUNC | os.O_WRONLY)
It does not work other wise.
精彩评论