Older Locking Techniques

In older UNIX implementations that lacked file locking, a number of ad hoc locking techniques were employed. Although all of these have been superseded by fcntl() record locking, we describe them here since they still appear in some older programs. All of these techniques are advisory in nature.

SUSv3 requires that an open() call with the flags O_CREAT and O_EXCL perform the steps of checking for the existence of a file and creating it atomically (Atomicity and Race Conditions). This means that if two processes attempt to create a file specifying these flags, it is guaranteed that only one of them will succeed. (The other process will receive the error EEXIST from open().) Used in conjunction with the unlink() system call, this provides the basis for a locking mechanism. Acquiring the lock is performed by successfully opening the file with the O_CREAT and O_EXCL flags, followed by an immediate close(). Releasing the lock is performed using unlink(). Although workable, this technique has several limitations:

The fact that calling open() on an existing file fails if O_TRUNC is specified and write permission is denied on the file can be used as the basis of a locking technique. To obtain a lock, we use the following code (which omits error checking) to create a new file:

fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, (mode_t) 0);
close(fd);

If the open() call succeeds (i.e., the file didn’t previously exist), we have the lock. If it fails with EACCES (i.e., the file exists and has no permissions for anyone), then another process has the lock, and we must try again later. This technique suffers the same limitations as the previous techniques, with the added caveat that we can’t employ it in a program with superuser privileges, since the open() call will always succeed, regardless of the permissions that are set on the file.