1

I have a requirement to create locks via fcntl to make a script run only once with a given argument. To achieve this, I create a file with the given argument and acquire lock on it. I have the below code written in python. For simplicity's sake I have hardcoded the filename as "mylockfile"

import traceback
from errno import EACCES, EAGAIN
from fcntl import lockf, LOCK_EX, LOCK_NB
from time import sleep

import os

if __name__ == '__main__':
   # Create lock file and write current pid into it
   fd = open("mylockfile", 'w')
   fd.write("%d " %os.getpid())
   try:
        x = lockf(fd, LOCK_EX | LOCK_NB)
        print("Obtained lock")
        # Do useful work
        sleep(10)

    except OSError as e:
        # Terminate in case of error

        if e.errno in (EACCES, EAGAIN):
            print("Script already running")
            print(e.errno)
        # Traceback of OSError
        traceback.print_exc()
        fd.close()
        exit(1)

    # Do other useful work

Now, the problem is when it goes to sleep, I manually delete the mylockfile and start another instance of the script. And, I expected it to fail acquiring the lock as previous process still has open file descriptor attached to it. But, it actually acquires the lock I am not sure why this is happening. And if this is expected behaviour, how do we make sure that the lockfiles are safe from deletion?

1

As soon as the lock file is deleted, any relation between the open file descriptor and the file name is lost. Hence there is no way for a new process to find out that there is still another process running.

There is also no way to protect the lock file from deletion beyond the usual unix permissions; given sufficient privileges the file can always be deleted. The process could regularly check whether the lock file still exists and react accordingly (either die or recreate the lock file) but there is no way to make that foolproof.

  • Thank you! In that case, is there a better alternative to make sure that the script doesn't get triggered multiple times? – Deepthi Nidwannaya Feb 2 '18 at 9:51
  • One way could be to open a listener socket on TCP with a special port number, it's impossible to open multiple listeners on a given IP/TCP port combination without special options. – wurtel Feb 2 '18 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.