MetallicPriest
MetallicPriest

Reputation: 30765

File lock for atomic access does not work

So, I want to execute some code which has to be atomic from different running programs in Python. For that purpose, I though about using File locks.

However, its not working. In the following code, what I am doing is to print a message given as an argument and then wait for 30 seconds before unlocking the file. In that case, If i run two instances, the 2nd instance would have to wait for that time to print the message. But this is not what happens, as both instances immediately print the message.

What mistake am I doing?

message = sys.argv[1]

lock_file = "test.lock"
_flock = None

def _lock_file():
        _flock = open(lock_file, 'w+')
        while True:
                try:
                        fcntl.flock(_flock, fcntl.LOCK_EX | fcntl.LOCK_NB)
                        break
                except IOError as e:
                        # raise on unrelated IOErrors
                        if e.errno != errno.EAGAIN:
                                raise
                        else:
                                time.sleep(0.1)


def _unlock_file():
        if _flock != None:
                fcntl.flock(_flock, fcntl.LOCK_UN)

_lock_file()
print(message)
time.sleep(30)
_unlock_file()

Upvotes: 1

Views: 634

Answers (1)

Vishnudev Krishnadas
Vishnudev Krishnadas

Reputation: 10960

For me, the below works, Why have a while True?

Use lockf instead of flock. It takes care of acquiring and releasing of locks better. The key difference is lockf is a mandatory lock. This means that when one process locks a section of a file, no other process can access that section of the file. flock , on the other hand is an advisory lock - meaning that processes must choose to agree to lock upon the file but the kernel will enforce no such thing.

import sys
import fcntl
import time

message = sys.argv[1]

lock_file = "test.lock"
_flock = open(lock_file, "w")

def lock_file(f):
        fcntl.lockf(f, fcntl.LOCK_EX)
def unlock_file(f):
        fcntl.lockf(f, fcntl.LOCK_UN)

lock_file(_flock)
print(message)
time.sleep(30)
unlock_file(_flock)

Upvotes: 1

Related Questions