[Bug 272367] openat(..., O_NONBLOCK | O_EXLOCK) may wrongly return EAGAIN

From: <bugzilla-noreply_at_freebsd.org>
Date: Tue, 04 Jul 2023 18:18:29 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=272367

            Bug ID: 272367
           Summary: openat(..., O_NONBLOCK | O_EXLOCK) may wrongly return
                    EAGAIN
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: asomers@FreeBSD.org
 Attachment #243203 text/plain
         mime type:

Created attachment 243203
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=243203&action=edit
Reproduction script

In a multithreaded program that involves forking, I sometimes see openat(...,
O_NONBLOCK | O_EXLOCK) return EAGAIN for a file that should be unlocked. 
ktrace clearly shows that only one thread access the file in question.  That
thread opens the file, does some I/O, then closes it.  Immediately after
closing it it tries to open again and that's when the openat fails.  ktrace
shows that no other thread tries to access the file in question.  However,
ktrace _also_ shows that another thread calls rfork while the first thread has
the file locked.

flock(2) says that locks are associated with files, not file descriptors.  So
if a process forks, the file should be unlocked whenever either the parent
calls close() or the child calls fdcloseexec().  I can't understand how in
neither case the file would fail to get unlocked, so I suspect a bug.

The attached test case can reproduce the problem with either ZFS or tmpfs.

Steps to Reproduce
==================

cc -O2 -Wall -g -l pthread -o o_exlock o_exlock.c
./o_exlock <N> /tmp/testfile

where N is greater than 1.

-- 
You are receiving this mail because:
You are the assignee for the bug.