Skip to content

Commit ffb3379

Browse files
committed
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: df63bd4 ("* cygheap.h (cygheap_fdmanip): New class: simplifies locking and retrieval of fds from cygheap->fdtab.") Reviewd-by: Ken Brown <[email protected]> Signed-off-by: Takashi Yano <[email protected]> (cherry picked from commit cec8a66)
1 parent 249b8e8 commit ffb3379

File tree

2 files changed

+9
-5
lines changed

2 files changed

+9
-5
lines changed

winsup/cygwin/release/3.6.2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ Fixes:
2222

2323
- Fix conserver-config error.
2424
https://cygwin.com/pipermail/cygwin/2025-April/258086.html
25+
26+
- Fix deadlock for opening both side of a fifo in a process.
27+
Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258138.html

winsup/cygwin/syscalls.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,11 +1472,6 @@ open (const char *unix_path, int flags, ...)
14721472
mode = va_arg (ap, mode_t);
14731473
va_end (ap);
14741474

1475-
cygheap_fdnew fd;
1476-
1477-
if (fd < 0)
1478-
__leave; /* errno already set */
1479-
14801475
/* When O_PATH is specified in flags, flag bits other than O_CLOEXEC,
14811476
O_DIRECTORY, and O_NOFOLLOW are ignored. */
14821477
if (flags & O_PATH)
@@ -1577,6 +1572,12 @@ open (const char *unix_path, int flags, ...)
15771572
if ((flags & O_TMPFILE) && !fh->pc.isremote ())
15781573
try_to_bin (fh->pc, fh->get_handle (), DELETE,
15791574
FILE_OPEN_FOR_BACKUP_INTENT);
1575+
1576+
cygheap_fdnew fd;
1577+
1578+
if (fd < 0)
1579+
__leave; /* errno already set */
1580+
15801581
fd = fh;
15811582
if (fd <= 2)
15821583
set_std_handle (fd);

0 commit comments

Comments
 (0)