setlock 1 user commands nosh
setlock open an exclusive lock file then chain
`setlock` --non-blocking --ignore file next-prog

## Description

`setlock` is a chain-loading utility that opens the lock file named file leaving an open file descriptor in the current process and then chain loads to next-prog with the execvp 3 function.

next-prog may contain its own command line options, which `setlock` will ignore.

The lock remains active whilst the file description, that is opened by this utility for the purpose, remains open (via a file descriptor) in any process; either the one that ran `setlock` or a child process that has inherited the file descriptor. Closing the file descriptor, by exiting the process(es) or otherwise, is the only portable operation allowed. It is unspecified what access rights the file descriptor has for the lock file, or whether the descriptor is in blocking mode.

Some code in a chained-to program (or child process) explicitly unlocking the file with flock 2 will also deactivate the lock. However, said code would have to discover the open file descriptor to use. `setlock` does not record it anywhere for programs to easily find.

`setlock` does not read from or write to the lockfile. On platforms where the implementation (discussed further on) permits locking special files, this allows using such files as lockfiles. Note, however, that since the file access is unspecified, it is unspecified whether using a FIFO with no reader open as a lockfile will work.

Unless the --non-blocking command line option is used, `setlock` will wait to obtain the lock whilst another process holds it. If that option is used, it will not wait, but instead will fail to acquire the lock.

Unless the --ignore option is used, failure to acquire the lock, because it isn't a valid lock file, because someone else has the lock and non-blocking mode has been used, or for some other reason, will cause `setlock` to print an error message and exit with a failure status instead of chaining. If that option is used, it will still exit on failure, but without printing an error message and with a success status.

## Unreliable implementation details and the NFS mess

### Précis

There is a broad range of tools that will interlock with this tool. However, there are also a couple of tools that do not, one of which shares its name and command-line syntax with a tool that does, making it important to know which of those tools one is using.
NFS has historically caused major problems with Unix locking, and that continues to be the case almost a quarter of the way into the 21st century. Using NFS continues to break this and other tools. Network fileserver protocols that attempt to provide Unix locking semantics started with AT&T Unix System 5 Release 3's RFS (Remote File Server) and continue with CIFS (a.k.a. SMB). One has to check carefully how the tools that one uses interact with the network fileserver protocol that one uses, both locally and remotely.

To summarize the summary of the summary: Unix file locking is a problem.

### Dramatis personæ

flock 2

  A whole-file advisory locking system call. Locks have the lifetime of the open file description. Child processes that inherit access to the open file description via inherited open file descriptors also hold the lock. They can explicitly unlock it with this system call.

  Although never standardized by POSIX or the Single Unix Specification, and originating with 4.2BSD, in the 21st century this exists on pretty much all relevant Unix or Unix-alike operating systems, and the historical notion that this may not exist is just that — historic. Daniel J. Bernstein's Unix portability notes from the 1990s state that this system call does not exist on SunOS. This is somewhat misleading, because its modern equivalent Illumos has a library function of this name, layered atop the fcntl 2 system call. The Linux Standard Base Core Specification guarantees the existence of this system call on Linux. And of course all of the BSDs have it.

open 2

  A system call that on some operating systems has an `O_EXLOCK` flag that opens the file and performs the equivalent of an exclusive flock 2 whole file lock, all in one call, eliminating a short window of opportunity where a process that creates a new lockfile might not be the first to advisory whole-file lock it.

lockf 2

  A system call that provides advisory record-locking mechanisms, with a mode that allows locking a single record that always spans the entire file. Locks have the lifetime of the locking process. Other processes do not share the lock, and closing any file descriptor referencing the open file description releases the lock.

  This was standardized by POSIX and the Single Unix Specification.

fcntl 2

  A system call that provides advisory record-locking mechanisms, with a mode that allows locking a single record that always spans the entire file, in two ways:

  - Locks that have the lifetime and scope of the locking process, just like lockf 2. This was standardized by POSIX and the Single Unix Specification.

  - Locks that have the lifetime of the open file description and scope of potentially multiple processes, just like flock 2. This has not been standardized by POSIX and the Single Unix Specification. Although there was an attempt to standardize it, as of 2023 that attempt is still stalled after many years.

`setlock`

  This utility. It uses the `O_EXLOCK` flag to the open 2 system call, if the operating system has it, falling back to using the flock 2 system call.

setlock 1

  A file locking utility from 1999 by Daniel J. Bernstein that was part of Bernstein's daemontools and is part of djbwares. This uses the flock 2 system call where it exists, falling back to the lockf 2 system call where it does not.

lockrun 1

  A standalone file locking utility from 2006 by Steve Friedl. This uses the flock 2 system call, with a compile-time selectable option to instead use the lockf 2 system call.

flock 1

  A file locking utility from 2003 by H. Peter Anvin that is part of the util-linux toolset. This uses the flock 2 system call.

flock 1

  A standalone file locking utility from 2014 by Joseph Holsten. This uses the fcntl 2 system call.

chpst 8

  A file locking utility by Gerrit Pape that is part of runit. This uses the flock 2 system call.

lockf 1

  A file locking utility from FreeBSD 2.2 by John Polstra. This uses the open 2 system call with the `O_EXLOCK` flag.

lckdo 1

  A file locking utility by Michael Tokarev that was part of moreutils. This uses the flock 2 system call, with a compile-time selectable option to instead use the fcntl 2 system call.

s6-setlock 8

  A file locking utility by Laurent Bercot that is part of s6. This uses the fcntl 2 system call.

### Details

Operating systems vary:

- Illumos and the BSDs guarantee that all whole-file and record advisory locking mechanisms interlock with all other advisory lock mechanisms, of any type. Applications that take out both forms, as a way of covering all of their bases, will actually deadlock themselves, and the Illumos and BSD manuals thus say to use one or the other and not both.

- Per Andy Walker's File Locking Release Notes Linux since May 1997 has provided the opposite guarantee, that they do not interlock. Applications that want to interlock at both the whole-file and record levels have to take out both forms of lock.

- Both Illumos and Linux provide the not-standardized open file description record locks of fcntl 2; but as aforementioned Illumos and Linux differ on whether they interlock with other locking mechanisms.

In general, the flock 2 system call is the widely recommended locking mechanism, and has been for decades, with the Linux manual politely describing the semantics of fcntl 2 and lockf 2 system call locking as "unfortunate" and the BSD manual more forthrightly talking about "the completely stupid semantics of System V" and POSIX. (Sharing the sentiment, Michael Tokarev comments in the source code of lckdo 1 on the "stupid POSIX fcntl locking semantics".)

No known utility makes use of the not-standardized open file description record locks of fcntl 2 provided by Illumos and Linux.

All bar two of the tools now use the flock 2 system call, either directly or via the `O_EXLOCK` flag to the open 2 system call. Bernstein setlock 1 never needs to fall back and Freidl lockrun 1 never requires its conditional compilation that was only introduced for SunOS and is obsoleted by Illumos. The others (including this `setlock`) simply have always used it, as it has been widely recognized as the correct choice since the 1990s, and the only real barrier to its universal use (its non-existence on historical operating systems like SunOS in the 1990s) has (by Illumos et al.) long since been removed.

All bar just those two tools, Bercot s6-setlock 8 and Holsten flock 1, will interlock on local filesystems. Their file locks are compatible with one another, and they will all interoperate with one another on local filesystems. In addition, the guarantees made by Illumos and the BSDs mean that even these two will interlock with all of the rest on those operating systems, on local filesystems.

Although AT&T System 5 Release 3's RFS (Remote File Server) fully supported locking, as does CIFS (a.k.a. SMB), NFS has been a thorn in the side of Unix locking, and all of these tools, since 1984. NFS's decades-long history of interacting in unexpected ways with file locking is in part fortunately now just that — history. However, several problems remain, still, as of 2023:

- The NFS implementation for Linux silently changes flock 2 locks by a client into lockf 2/fcntl 2 locks on the server, throwing a giant spanner in the works for all of these tools because whether they interlock now also depends from whether a utility is run on an NFS client or locally on the NFS server without going through NFS. Thus nominally interlocking locks actually do not interlock, and nominally not interlocking locks actually do interlock (contra Andy Walker and the Linux documentation).

  The Bercot and Holsten utilities run on the server will interlock with all of the other utilities run on the client; but will only interlock with each other on the server, and not with any other utilities.
  All of the others bar those two will interlock with one another on clients, and if they are all running on the server together and not going through NFS; but will not interlock with one another if they are used on a mixture of a client and the server.

- Illumos documentation explicitly states that locking with the flock 3 system call is not supported at all over NFS.

  Thus all bar the Bercot and Holsten utilities will not function over NFS on Illumos; despite that as aforementioned all all of these tools interoperate on local filesystems on Illumos.

## Author

Jonathan de Boyne Pollard