Skip to content

Commit 6732cd5

Browse files
tyan0lazka
authored andcommitted
Cygwin: open: Unlock fdtab before open_with_arch()
Since the commit 31bf91f, opening fifo causes a deadlock. This is because, open_with_arch() for fifo can be blocked until the other side of the fifo is opened. The commit 31bf91f moves the creating cygheap_fdnew before open_with_arch() to address the issue: https://cygwin.com/pipermail/cygwin/2026-May/259664.html However, cygheap_fdnew locks fdtab, so open() for the other side of fifo cannot create cygheap_fdnew until fdtab is unlocked. This is the cause of the deadlock. With this patch, fdtab is unlocked before open_with_arch(), but marked as used using tentative fhandler. The summary of open() is as follows. 1) Lock fdtab. 2) Create new fd. 3) Mark fd as used using tentative fhandler. 4) Unlock fdtab. 5) Call open_with_arch(). 6) Set final fhandler to fd. The important point is that create fd before open_with_arch() to address https://cygwin.com/pipermail/cygwin/2026-May/259664.html, but unlock fdtab before open_with_arch() to address https://cygwin.com/pipermail/cygwin/2026-July/259884.html. Fixes: 31bf91f ("Cygwin: Ensure unused fd available for open()") Addresses: https://cygwin.com/pipermail/cygwin/2026-July/259884.html Reported-by: kikairoya <kikairoya@gmail.com> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp> Reviewed-by: Mark Geisert <mark@maxrnd.com> (cherry picked from commit 524d75f)
1 parent 9a6cbe5 commit 6732cd5

1 file changed

Lines changed: 17 additions & 3 deletions

File tree

winsup/cygwin/syscalls.cc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,7 @@ extern "C" int
14511451
open (const char *unix_path, int flags, ...)
14521452
{
14531453
int res = -1;
1454+
int fd = -1;
14541455
va_list ap;
14551456
mode_t mode = 0;
14561457
fhandler_base *fh = NULL;
@@ -1550,9 +1551,12 @@ open (const char *unix_path, int flags, ...)
15501551
/* Reserve an fdtable entry here, before calling open_with_arch() below.
15511552
Otherwise there's a tiny chance of hitting OPEN_MAX further on which
15521553
could create a new file without any way for Cygwin to refer to it. */
1553-
cygheap_fdnew fd;
1554+
cygheap->fdtab.lock();
1555+
fd = cygheap->fdtab.find_unused_handle ();
15541556
if (fd < 0)
1555-
__leave; /* errno already set */
1557+
__leave; /* errno already set */
1558+
cygheap->fdtab[fd] = fh; /* tentative setting to mark as used */
1559+
cygheap->fdtab.unlock();
15561560

15571561
if (fh->dev () == FH_PROCESSFD && fh->pc.follow_fd_symlink ())
15581562
{
@@ -1580,13 +1584,23 @@ open (const char *unix_path, int flags, ...)
15801584
try_to_bin (fh->pc, fh->get_handle (), DELETE,
15811585
FILE_OPEN_FOR_BACKUP_INTENT);
15821586

1583-
fd = fh;
1587+
cygheap->fdtab.lock ();
1588+
cygheap->fdtab[fd] = fh;
1589+
fh->inc_refcnt ();
1590+
cygheap->fdtab.unlock ();
1591+
15841592
if (fd <= 2)
15851593
set_std_handle (fd);
15861594
res = fd;
15871595
}
15881596
__except (EFAULT) {}
15891597
__endtry
1598+
if (res < 0 && fd >= 0)
1599+
{
1600+
cygheap->fdtab.lock ();
1601+
cygheap->fdtab[fd] = NULL; /* Mark as unused */
1602+
cygheap->fdtab.unlock ();
1603+
}
15901604
if (res < 0 && fh)
15911605
delete fh;
15921606
syscall_printf ("%R = open(%s, %y)", res, unix_path, flags);

0 commit comments

Comments
 (0)