fcntl couldn't lock /dev/null and hang
A minimal working example, but only for my machine:
int main(int argc, char* argv[]) { int fd = open ("/dev/null", O_RDWR|O_CREAT); if (fd < 0) { printf("Failed to open file\n"); } struct flock lock; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; int res = fcntl(fd, F_SETLKW,&lock); // this hangs if (res < 0) { printf("Failed to lock\n"); } close (fd); return (0);
}The program above hangs only on my machine, and completed instantly on 7 other machines. Is there anything that I can look into to investigate this problem?
strace shows that fcntl was getting stuck when the program (./t) was killed by ^C.
5249 execve("./t", ["./t"], [/* 23 vars */]) = 0
5249 brk(NULL) = 0x1cf6000
5249 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
5249 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
5249 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
5249 fstat(3, {st_mode=S_IFREG|0644, st_size=98358, ...}) = 0
5249 mmap(NULL, 98358, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f31a1118000
5249 close(3) = 0
5249 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
5249 open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
5249 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
5249 fstat(3, {st_mode=S_IFREG|0755, st_size=1868984, ...}) = 0
5249 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f31a1117000
5249 mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f31a0b42000
5249 mprotect(0x7f31a0d02000, 2097152, PROT_NONE) = 0
5249 mmap(0x7f31a0f02000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7f31a0f02000
5249 mmap(0x7f31a0f08000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f31a0f08000
5249 close(3) = 0
5249 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f31a1116000
5249 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f31a1115000
5249 arch_prctl(ARCH_SET_FS, 0x7f31a1116700) = 0
5249 mprotect(0x7f31a0f02000, 16384, PROT_READ) = 0
5249 mprotect(0x600000, 4096, PROT_READ) = 0
5249 mprotect(0x7f31a1131000, 4096, PROT_READ) = 0
5249 munmap(0x7f31a1118000, 98358) = 0
5249 open("/dev/null", O_RDWR|O_CREAT, 03777762203636510) = 3
5249 fcntl(3, F_SETLKW, {l_type=F_WRLCK, l_whence=SEEK_SET, l_start=0, l_len=0}) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
5249 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
5249 +++ killed by SIGINT +++ 4 1 Answer
I'm answering my own question. @steeldriver's comment was very useful, it helped me to understand what was the problem.
You are asking fnctl to obtain an exclusive (write) lock
l_type=F_WRLCK, where (according toman fnctl)F_SETLKWmeans "... but if a conflicting lock is held on the file, then wait for that lock to be released". You may be able to see why there is a conflicting lock usinglslocks- see How to list processes locking file?. If you don't wantfnctlto wait in the case of conflict, then tryF_SETLKin place ofF_SETLKW. Regardless, @vidarlo 's point applies - it doesn't seem like a good idea to be write-locking/dev/null.
For those who are interested in this problem, it was docker daemon that locked /dev/null on my machine. Some more information can be found here:
As why I need to lock /dev/null, I have a testsuite that writes to /dev/null instead of writing to the network. The testsuite is for a different component, written by a different team based in a different continent. So it is not clear for me either :)