Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 Apr 2015 16:18:09 -0500
From:      Guy Helmer <guy.helmer@gmail.com>
To:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   lockf() vs. flock() -- lockf() not locking?
Message-ID:  <3950D855-0F4E-49E0-A388-4C7ED102B68B@gmail.com>

next in thread | raw e-mail | index | archive | help
Recently an application I use switched from using flock() for advisory =
file locking to lockf() in the code that protects against concurrent =
writes to a file that is being shared and updated by multiple processes =
(not threads in a single process). The code seems reliable =E2=80=94 a =
lock manager class opens the file & obtains the lock, then the =
read/update method opens the file using a separate file descriptor & =
reads/writes the file, flushes & closes the second file descriptor, and =
then destroys the lock manager object which unlocks the file & closes =
the first file descriptor.

Surprisingly this simple change seems to have made the code unreliable =
by allowing concurrent writers to the file and corrupting its contents:

-    if (flock(fd, LOCK_EX) !=3D 0)
+    if (lockf(fd, F_LOCK, 0) !=3D 0)
         throw std::runtime_error("Failed to get a lock of " + =
filename);

. . .
     if (fd !=3D -1) {
-        flock(fd, LOCK_EX);
+        lockf(fd, F_ULOCK, 0);
         close(fd);
         fd =3D -1;
     }

=46rom my reading of the lockf(3) man page and reviewing the =
implementation in lib/libc/gen/lockf.c, and corresponding code in =
sys/kern/kern_descrip.c, it appears the lockf() call should be =
successfully obtaining an advisory lock over the whole file like a =
successful flock() did. However, I have a stress test that quickly =
corrupts the target file using the lockf() implementation, and the test =
fails to cause corruption using the flock() implementation. I=E2=80=99ve =
instrumented the code, and it's clear that multiple processes are =
simultaneously in the block of code after the =E2=80=9Clockf(fd, F_LOCK, =
0)=E2=80=9D line.

Am I missing something obvious? Any ideas?

Thanks,
Guy




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3950D855-0F4E-49E0-A388-4C7ED102B68B>