Question

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 what that is. Can anyone help?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top