[PATCH] Cygwin: pipe: Restore blocking mode of read pipe on close()

Takashi Yano takashi.yano@nifty.ne.jp
Fri Aug 30 14:15:44 GMT 2024


If a cygwin app is executed from a non-cygwin app and the cygwin
app exits, read pipe remains on non-blocking mode because of the
commit fc691d0246b9. Due to this behaviour, the non-cygwin app
cannot read the pipe correctly after that. With this patch, the
blocking mode of the read pipe is stored into was_blocking_read_pipe
on set_pipe_non_blocking() when the cygwin app starts and restored
on close().

Addresses: https://github.com/git-for-windows/git/issues/5115
Fixes: fc691d0246b9 ("Cygwin: pipe: Make sure to set read pipe non-blocking for cygwin apps.");
Reported-by: isaacag, Johannes Schindelin <Johannes.Schindelin@gmx.de>
Reviewed-by:
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
---
 winsup/cygwin/fhandler/pipe.cc          | 12 ++++++++++++
 winsup/cygwin/local_includes/fhandler.h |  1 +
 2 files changed, 13 insertions(+)

diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc
index 852076ccc..5c760d704 100644
--- a/winsup/cygwin/fhandler/pipe.cc
+++ b/winsup/cygwin/fhandler/pipe.cc
@@ -55,6 +55,15 @@ fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
   IO_STATUS_BLOCK io;
   FILE_PIPE_INFORMATION fpi;
 
+  if (get_device () == FH_PIPER && nonblocking && !was_blocking_read_pipe)
+    {
+      status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
+				       FilePipeInformation);
+      if (NT_SUCCESS (status))
+	was_blocking_read_pipe =
+	  (fpi.CompletionMode == FILE_PIPE_QUEUE_OPERATION);
+    }
+
   fpi.ReadMode = FILE_PIPE_BYTE_STREAM_MODE;
   fpi.CompletionMode = nonblocking ? FILE_PIPE_COMPLETE_OPERATION
     : FILE_PIPE_QUEUE_OPERATION;
@@ -95,6 +104,7 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode, int64_t uniq_id)
        even with FILE_SYNCHRONOUS_IO_NONALERT. */
     set_pipe_non_blocking (get_device () == FH_PIPER ?
 			   true : is_nonblocking ());
+  was_blocking_read_pipe = false;
 
   /* Store pipe name to path_conv pc for query_hdl check */
   if (get_dev () == FH_PIPEW)
@@ -734,6 +744,8 @@ fhandler_pipe::close ()
     CloseHandle (query_hdl);
   if (query_hdl_close_req_evt)
     CloseHandle (query_hdl_close_req_evt);
+  if (was_blocking_read_pipe)
+    set_pipe_non_blocking (false);
   int ret = fhandler_base::close ();
   ReleaseMutex (hdl_cnt_mtx);
   CloseHandle (hdl_cnt_mtx);
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
index 8b02a2b1b..16c39b55b 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -1216,6 +1216,7 @@ private:
   HANDLE query_hdl_proc;
   HANDLE query_hdl_value;
   HANDLE query_hdl_close_req_evt;
+  bool was_blocking_read_pipe;
   void release_select_sem (const char *);
   HANDLE get_query_hdl_per_process (OBJECT_NAME_INFORMATION *);
 public:
-- 
2.45.1



More information about the Cygwin-patches mailing list