On Fri, 14 Nov 2025 11:27:04 -0800
Nahor wrote:
> If `flock()` was used on the same file descriptor, then this might
> have been a valid point. However, each thread has its own file
> descriptor in this case, so this would be very surprising if it wasn't
> thread-safe.

IIUC, flock() locks file itself, but not file descriptor. Usually,
flock() is used for inter-process file protection, isn't it?

> Moreover, it's not just `flock()` failing, it's also (and mostly!)
> `open()` that fails. And it's the `open()` for a completely different
> file than the one being locked. So that would suggest that `open()` is
> not also not MT-safe. And not safe when using different files. And not
> safe across multiple different functions (flock+open).

Indeed, this is really weird. I looked into this, and found 'upath' in
path.cc is destroyed after 'NtCreateFile()' call at the following line.

I added assertion as follows:

diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 710775e38..562100161 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -3189,6 +3189,8 @@ restart:
         symlink (which would spoil the task of this method quite a bit).
         Fortunately it's ignored on most other file systems so we don't have
         to special case NFS too much. */
+      wchar_t c;
+      c = upath.Buffer[0];
       status = NtCreateFile (&h,
                             READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA,
                             &attr, &io, NULL, 0, FILE_SHARE_VALID_FLAGS,
@@ -3196,6 +3198,7 @@ restart:
                             FILE_OPEN_REPARSE_POINT
                             | FILE_OPEN_FOR_BACKUP_INTENT,
                             eabuf, easize);
+      assert (upath.Buffer[0] == c);
       debug_printf ("%y = NtCreateFile (%S)", status, &upath);
       /* No right to access EAs or EAs not supported? */
       if (!NT_SUCCESS (status)

then, the assertion fails for your test case like:
tmp_dir: /tmp/flockAQ4Hbb
assertion "upath.Buffer[0] == c" failed: file 
"../../.././winsup/cygwin/path.cc", line 3201, function: int 
symlink_info::check(char*, const suffix_info*, fs_info&, path_conv_handle&)
                      Abort

Does another thread destroy the puthbuf? But pathbuf is thread local, IIUC.
Corinna, have you noticed anything?

> And more generally, I've never heard of file operations not being
> thread safe. Atomicity and ordering are common problems, but not
> thread safety.

The linux man page for flock() does not mention about MT-safe
https://man7.org/linux/man-pages/man2/flock.2.html

while it mentions about MT-safe for
https://man7.org/linux/man-pages/man3/lockf.3.html

So I doubt flock() should really be MT-safe.

-- 
Takashi Yano <[email protected]>

-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to