0

I have a Bash script that needs to lock a file for exclusive read/write while it runs. During this time, any other copies of the same script running should hang until the lock is released (which should be pretty quickly).

#!/bin/bash
trap "rm -f /tmp/.lock; exit" 0 1 2 3 15
(
 flock -x 100 
 # Stuff happens here...
) 100>/tmp.lock

This works, somewhat. But not in these conditions:

  1. Start script copy #1
  2. Start script copy #2
  3. End script copy #1 before script copy #2 does

At this point, I get the error:

rm: cannot remove '/tmp/.lock': Text file busy

I assume I'm totally wrong on how I'm cleaning things up with the trap, so any help would be much appreciated. Thanks!

asked Apr 20, 2015 at 21:41
3
  • 2
    You lock files and not filenames, so I would question removing this file at all: you can run as many instances of ( flock -x 100; echo lock grabbed; rm /tmp/lol; sleep 60; ) 100> /tmp/lol as you want, and they'll all successfully lock /tmp/lol at the same time because the same filename keeps referring to different files. Commented Apr 20, 2015 at 21:50
  • BTW, most systems will allow this rm -f to happen without any text file busy error, instead silently breaking your locking. Consider yourself lucky that your particular Linux distro provides security hardening that saved you from this bug. Commented Apr 20, 2015 at 22:08
  • (On a different point -- trapping 0 would be sufficient; an EXIT trap covers all cases of exiting due to trappable signals). Commented Apr 20, 2015 at 22:23

1 Answer 1

5

DO NOT EVER try to "clean up" flock-style lockfiles whenever it is possible that any program holding that lock could be running or attempting to run.

Keep in mind that locks are held on inodes, not filenames. Deleting a directory entry decouples the inode previously at that location from its name, allowing that name to then refer to a different inode.

Consider the following scenario:

  1. Program A holds a lock.
  2. Program B opens the lockfile and tries to grab a lock on it, blocking until Program A is done with the lock.
  3. Program A finishes; closes the lock; and deletes the lockfile.
  4. Program B still holds a handle on the deleted lockfile. As Program A closed the lock (or exited, releasing its file handle and thus its lock), Program B is able to continue running, holding that handle as its lock.
  5. Program C tries to grab the lock. Even though Program B is still running, because the lockfile Program B holds a handle on was deleted by Program A, Program C is allowed to run concurrently.
  6. Program B exits, deleting the lockfile that Program C created, while Program C is still running.

Flock-file lockfiles should be considered mappings from filesystem namespace into file-locking namespace. These mappings do not need to be, and should not be, "cleaned up". You may wish to consider whether your operating system's filesystem hierarchy standard provides a places for such files to live, such as /var/lock, or somewhere on tmpfs (where "cleanup" will happen implicitly -- and safely -- on reboot).

answered Apr 20, 2015 at 21:54
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.