Understanding when to use and not use the -F option for flock(1)

September 29, 2019

A while back I wrote some notes on understanding how to use flock(1), but those notes omitted a potentially important option, partly because that option was added somewhere in between version util-linux version 2.27.1 (which is what Ubuntu 16.04 has) and version 2.31.1 (Ubuntu 18.04). That is the -F option, which is described in the manpage as:

Do not fork before executing command. Upon execution the flock process is replaced by command which continues to hold the lock. [...]

This option is incompatible with -o, as mentioned in the manpage.

The straightforward situation where you very much want to use -F is if you're trying to run a program that reacts specially to Control-C. If you run 'flock program', there will still be a flock process, it will get Control-C and exit, and undesirable things will probably happen. If you use 'flock -F program', there is only the program and it can react properly to Control-C without any side effects on other processes.

(I'm assuming here that if you ran flock and the program from inside a shell script, you ran it with 'exec flock ...'. If you're in a situation where you have to do things in your shell script after the program finishes, you can't solve the Control-C problem just with this.)

However, there is also a situation where you don't want to use -F, and to see it we need to understand how the flock lock is continued to be held by the command. As covered in the first note, flock(1) works through flock(2), which means that the lock is 'held' by having the flock()'d file descriptor still be open. Most programs are indifferent to inheriting extra file descriptors, so this additional descriptor from flock just hangs around, keeping the lock held. However, some programs actively seek out and close file descriptors they may have inherited, often to avoid leaking them into child processes. If you use 'flock -F' with such a program, your lock will be released prematurely (before the program exits) when the program does this.

(The existence of such programs is probably part of why flock -F is not the default behavior.)

Sidebar: Faking 'flock -F' if you don't have it

If you have a shell script that has to run on Ubuntu 16.04 and you need this behavior, you can fake it with 'flock -o'. It goes like this:

exec 9 >>/some/lockfile
flock -x -n 9 || exit 0
exec program ...

Since 'flock -F' locks some file descriptor and then exec's the program, we can imitate it by doing the same manually; we pick a random file descriptor number, get the shell to open a file on that file descriptor and leave it open, flock that file descriptor, and then have the shell exec our program. Our program will inherit the locked fd 9 and the lock remains for as long as fd 9 is open. When the program exits, all of its file descriptors will be closed, including fd 9, and the lock will be released.

Written on 29 September 2019.
« Some field notes on imposing memory resource limits on users on Ubuntu 18.04
ZFS performance really does degrade as you approach quota limits »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Sep 29 00:59:06 2019
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.