[PATCH] Cygwin: pipe: Add workaround for native ninja

Takashi Yano takashi.yano@nifty.ne.jp
Mon Mar 31 13:27:11 GMT 2025


Native (non-cygwin) ninja creates pipe with size == 0, and starts
cygwin process with that pipe. This causes infinite loop in the
fhandler_fifo_pipe::raw_write(). Ideally, the pipe implementation
in cygwin could work even with pipe size == 0, however, it seems
impossible due to:

(1) select() does not work for that pipe because PeekNamedPipe()
    always returns 0. Read side is ready to read only when the
    write side is about to write, but there is no way to know that.
(2) The cause of the problem:
    https://cygwin.com/pipermail/cygwin/2025-January/257143.html
    cannot be avoidable. To avoid CancelIo() problem, the patch
    https://cygwin.com/pipermail/cygwin-patches/2025q1/013451.html
    restricts the data size less than the current pipe space.
    However, if pipe size is zero this is impossible.

This patch adds just a workaround for native ninja that avoid
infinite loop in raw_write().

Addresses: https://github.com/msys2/msys2-runtime/issues/270
Reported-by: Christoph Reiter <reiter.christoph@gmail.com>
Co-authored-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Reviewed-by:
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
---
 winsup/cygwin/fhandler/pipe.cc | 5 +++++
 winsup/cygwin/select.cc        | 4 +++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc
index ac8bbe7d6..e35d523bb 100644
--- a/winsup/cygwin/fhandler/pipe.cc
+++ b/winsup/cygwin/fhandler/pipe.cc
@@ -455,6 +455,11 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
   ssize_t avail = pipe_buf_size;
   bool real_non_blocking_mode = false;
 
+  /* Workaround for native ninja. Native ninja creates pipe with size == 0,
+     and starts cygwin process with that pipe. */
+  if (avail == 0)
+    avail = PIPE_BUF;
+
   if (pipe_mtx) /* pipe_mtx is NULL in the fifo case */
     {
       DWORD timeout = is_nonblocking () ? 0 : INFINITE;
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 422c8e830..bb141b065 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -670,7 +670,9 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode)
 			   fpli.WriteQuotaAvailable);
 	  return fpli.WriteQuotaAvailable;
 	}
-      /* TODO: Buffer really full or non-Cygwin reader? */
+      return PIPE_BUF; /* Workaround for native ninja. Native ninja creates
+			  pipe with size == 0, and starts cygwin process
+			  with that pipe. */
     }
   else if (fpli.ReadDataAvailable)
     {
-- 
2.45.1



More information about the Cygwin-patches mailing list