[newlib-cygwin/cygwin-3_6-branch] Cygwin: open: Fix deadlock for opening fifo both side in a process

Takashi Yano tyan0@sourceware.org
Fri May 16 21:28:46 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=ffb33791d4c2f9f09488c268ba8233dd02255dff

commit ffb33791d4c2f9f09488c268ba8233dd02255dff
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date:   Sat May 17 00:46:41 2025 +0900

    Cygwin: open: Fix deadlock for opening fifo both side in a process
    
    Currently, opening both side of fifo in a process hangs if the
    read side is opened first. The following test case exhibit the
    hang while it works in linux.
    
      #include <unistd.h>
      #include <pthread.h>
      #include <sys/stat.h>
      #include <fcntl.h>
    
      #define fifo1 "/tmp/fifo-test"
    
      void *thr1(void *)
      {
        int fd;
        usleep(100000);
        fd = open(fifo1, O_WRONLY);
        write(fd, "A", 1);
        usleep(100000);
        close(fd);
        return NULL;
      }
    
      int main()
      {
        int fd;
        pthread_t th;
        char c;
        mkfifo(fifo1, 0600);
        pthread_create(&th, NULL, thr1, NULL);
        fd = open(fifo1, O_RDONLY);
        pthread_join(th, NULL);
        read(fd, &c, 1);
        write(1, &c, 1);
        close(fd);
        unlink(fifo1);
        return 0;
      }
    
    The mechanism of hang is as follows. The main thread tries to open
    the fifo for reading, but fhandler_fifo::open blocks until it detects
    that someone is opening the fifo for writing. The other thread wants
    to do that, but it never gets to the point of calling fhandler_fifo::
    open because it is stuck waiting for the lock on cygheap->fdtab.
    
    To fix this, this patch delays the construction of the cygheap_fdnew
    object fd until after fhandler_fifo::open has been called.
    
    Fixes: df63bd490a52 ("* cygheap.h (cygheap_fdmanip): New class: simplifies locking and retrieval of fds from cygheap->fdtab.")
    Reviewd-by: Ken Brown <kbrown@cornell.edu>
    Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
    (cherry picked from commit cec8a6680ea1fe38f38001b06c34ae355a785209)

Diff:
---
 winsup/cygwin/release/3.6.2 |  3 +++
 winsup/cygwin/syscalls.cc   | 11 ++++++-----
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/winsup/cygwin/release/3.6.2 b/winsup/cygwin/release/3.6.2
index e0c1d705f..915bd0150 100644
--- a/winsup/cygwin/release/3.6.2
+++ b/winsup/cygwin/release/3.6.2
@@ -22,3 +22,6 @@ Fixes:
 
 - Fix conserver-config error.
   https://cygwin.com/pipermail/cygwin/2025-April/258086.html
+
+- Fix deadlock for opening both side of a fifo in a process.
+  Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258138.html
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index c93bf4c95..d6a2c2d3b 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1472,11 +1472,6 @@ open (const char *unix_path, int flags, ...)
       mode = va_arg (ap, mode_t);
       va_end (ap);
 
-      cygheap_fdnew fd;
-
-      if (fd < 0)
-	__leave;		/* errno already set */
-
       /* When O_PATH is specified in flags, flag bits other than O_CLOEXEC,
 	 O_DIRECTORY, and O_NOFOLLOW are ignored. */
       if (flags & O_PATH)
@@ -1577,6 +1572,12 @@ open (const char *unix_path, int flags, ...)
       if ((flags & O_TMPFILE) && !fh->pc.isremote ())
 	try_to_bin (fh->pc, fh->get_handle (), DELETE,
 		    FILE_OPEN_FOR_BACKUP_INTENT);
+
+      cygheap_fdnew fd;
+
+      if (fd < 0)
+	__leave;		/* errno already set */
+
       fd = fh;
       if (fd <= 2)
 	set_std_handle (fd);


More information about the Cygwin-cvs mailing list