I kinda always knew file locking on Unix is a mess, but didn't realize how massive the mess is…
Jeremy Allison wrote in https://www.samba.org/samba/news/articles/low_point/tale_two_stds_os2.html:
What do you think the effect of this code on the lock created on the first file descriptor should be (so long as the close() call returns zero) ? If you answered "it should be silently removed when the second file descriptor was closed", congratulations, you have the same warped mind as the people who implemented the POSIX spec. Yes, that's correct. Any successful close() call on any file descriptor referencing a file with locks will drop all the locks on that file, even if they were obtained on another, still open, file descriptor.
Let me be clear to everyone: this behavior is never what you would want. Even experienced programmers are surprised by this behavior, because it makes no sense. Even after I've described this to Linux kernel hackers their response has been one of stunned silence, followed by a "but why would it do that"?
In order to discover if this functionality was actually correctly used by any application program or anything really depended on it, Andrew Tridgell, the original author of Samba once hacked the kernel on his Linux laptop to write a kernel debug message if ever this condition occurred. After a week of continuous use he found one message logged. When he investigated it turned out be be a bug in the "exportfs" NFS file exporting command, where a library routine was opening and closing the /etc/exports file that had been opened and locked by the main exportfs code. Obviously the authors didn't expect it to do that either.
The reason is historical and reflects a flaw in the POSIX standards process, in my opinion, one that hopefully won't be repeated in the future. I finally tracked down why this insane behavior was standardized by the POSIX committee by talking to long-time BSD hacker and POSIX standards committee member Kirk McKusick (he of the BSD daemon artwork). As he recalls, AT&T brought the current behavior to the standards committee as a proposal for byte-range locking, as this was how their current code implementation worked. The committee asked other ISVs if this was how locking should be done. The ISVs who cared about byte range locking were the large database vendors such as Oracle, Sybase and Informix (at the time). All of these companies did their own byte range locking within their own applications, none of them depended on or needed the underlying operating system to provide locking services for them. So their unanimous answer was "we don't care". In the absence of any strong negative feedback on a proposal, the committee added it "as-is", and took as the desired behavior the specifics of the first implementation, the brain-dead one from AT&T.