Package: lsof Version: 4.91+dfsg-1 Severity: normal Dear Maintainer,
The output of lsof is misleading when it comes to "flock" and "OFD" file locks on Linux. Background: there are three types of advisory file locks in Linux: - "flock" or "BSD" locks, which are created by the flock system call. These are associated with a particular *open file description*, so they are inherited by child processes. - "fcntl" or "POSIX" locks, which are created by the fcntl system call with the F_SETLK or F_SETLKW option. These are associated with a particular *process ID*, so they are not inherited by child processes. - "OFD" locks, which are created by the fcntl system call with the F_OFD_SETLK or F_OFD_SETLKW option. These are like flock locks in that they are associated with an open file description, but they are like fcntl locks in that they apply to a particular range of bytes. The kernel reports all of these locks via /proc/locks, and lsof parses that file and tries to indicate which processes are currently holding locks on which files. However, the information in /proc/locks is incomplete and in some cases inaccurate: for flock and OFD locks, it tells you that *some process* is holding a lock on the file, but it doesn't tell you which one(s), since the lock may have been inherited across a fork. The proc(5) manpage states: Because OFD locks are not owned by a single process (since multiple processes may have file descriptors that refer to the same open file description), the value -1 is displayed in [the process ID field] for OFD locks. (Before kernel 4.14, a bug meant that the PID of the process that initially acquired the lock was displayed instead of the value -1.) The manpage doesn't mention that exactly the same "bug" also applies to flock locks. As far as I can see, this does appear to be a limitation of the kernel: I don't know of any way that lsof could possibly figure out which processes, or which file descriptors, are associated with a particular lock. So although I believe this is a bug in lsof, I don't think it is one that lsof can fix by itself. Nonetheless, it's a limitation that probably should be better documented, and perhaps lsof's output could be improved to reflect this uncertainty - for example, it could display a '?' in the lock column to indicate "*some* process has a lock on this file; this particular process might or might not." Here is an example program: #define _GNU_SOURCE #include <err.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/file.h> #include <sys/wait.h> #include <unistd.h> int main() { int fd1, fd2, fd3, fd4, status; pid_t child; struct flock fl = { 0 }; char cmd[100]; fd1 = open("/tmp/file1", O_RDWR | O_CREAT, 0600); fd2 = open("/tmp/file1", O_RDWR | O_CREAT, 0600); fd3 = open("/tmp/file2", O_RDWR | O_CREAT, 0600); fd4 = open("/tmp/file2", O_RDWR | O_CREAT, 0600); if (fd1 < 0 || fd2 < 0 || fd3 < 0 || fd4 < 0) err(1, "open"); if (flock(fd1, LOCK_SH)) err(1, "flock"); fl.l_type = F_WRLCK; if (fcntl(fd3, F_OFD_SETLKW, &fl)) err(1, "fcntl"); child = fork(); if (child < 0) err(1, "fork"); else if (child == 0) { snprintf(cmd, sizeof(cmd), "lsof -p %d,%d -a -d 3-99", getppid(), getpid()); system(cmd); } else { wait(&status); } return 0; } Running this program produces: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME a.out 5615 benjamin 3uR REG 0,44 0 517883 /tmp/file1 a.out 5615 benjamin 4uR REG 0,44 0 517883 /tmp/file1 a.out 5615 benjamin 5u REG 0,44 0 517884 /tmp/file2 a.out 5615 benjamin 6u REG 0,44 0 517884 /tmp/file2 a.out 5616 benjamin 3u REG 0,44 0 517883 /tmp/file1 a.out 5616 benjamin 4u REG 0,44 0 517883 /tmp/file1 a.out 5616 benjamin 5u REG 0,44 0 517884 /tmp/file2 a.out 5616 benjamin 6u REG 0,44 0 517884 /tmp/file2 The flock lock is indicated (with an "R") for the parent process, but not for the child process; the OFD lock is not indicated at all. (If you run the same program on an older kernel, it will show a "W" in the fourth and fifth lines.) To be *really* precise, file descriptors 3 and 5 are the ones holding the locks; those FDs should have an "R" or "W" next to them while 4 and 6 shouldn't. -- System Information: Debian Release: 10.2 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable-debug'), (500, 'stable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 4.19.0-6-amd64 (SMP w/40 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages lsof depends on: ii libc6 2.28-10 ii libselinux1 2.8-1+b1 lsof recommends no packages. Versions of packages lsof suggests: ii perl 5.28.1-6 -- debconf-show failed