|
| 1 | +From a4d92d60dc618a2c1207dab20dcd04b4fb7cb541 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Takashi Yano < [email protected]> |
| 3 | +Date: Mon, 11 Mar 2024 22:08:00 +0900 |
| 4 | +Subject: [PATCH 79/N] Cygwin: pipe: Make sure to set read pipe non-blocking |
| 5 | + for cygwin apps. |
| 6 | + |
| 7 | +If pipe reader is a non-cygwin app first, and cygwin process reads |
| 8 | +the same pipe after that, the pipe has been set to bclocking mode |
| 9 | +for the cygwin app. However, the commit 9e4d308cd592 assumes the |
| 10 | +pipe for cygwin process always is non-blocking mode. With this patch, |
| 11 | +the pipe mode is reset to non-blocking when cygwin app is started. |
| 12 | + |
| 13 | +Backported-from: 55431b408e (Cygwin: pipe: Make sure to set read pipe non-blocking for cygwin apps., 2024-03-11) |
| 14 | +Addresses: https://cygwin.com/pipermail/cygwin/2024-March/255644.html |
| 15 | +Fixes: 9e4d308cd592 ("Cygwin: pipe: Adopt FILE_SYNCHRONOUS_IO_NONALERT flag for read pipe.") |
| 16 | +Reported-by: wh < [email protected]> |
| 17 | +Reviewed-by: Corinna Vinschen < [email protected]> |
| 18 | +Signed-off-by: Takashi Yano < [email protected]> |
| 19 | +Signed-off-by: Johannes Schindelin < [email protected]> |
| 20 | +--- |
| 21 | + winsup/cygwin/fhandler/pipe.cc | 63 +++++++++++++++++++++++++ |
| 22 | + winsup/cygwin/local_includes/fhandler.h | 3 ++ |
| 23 | + winsup/cygwin/spawn.cc | 34 +------------ |
| 24 | + 3 files changed, 68 insertions(+), 32 deletions(-) |
| 25 | + |
| 26 | +diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc |
| 27 | +index 05b1625..8daae8d 100644 |
| 28 | +--- a/winsup/cygwin/fhandler/pipe.cc |
| 29 | ++++ b/winsup/cygwin/fhandler/pipe.cc |
| 30 | +@@ -18,6 +18,7 @@ details. */ |
| 31 | + #include "pinfo.h" |
| 32 | + #include "shared_info.h" |
| 33 | + #include "tls_pbuf.h" |
| 34 | ++#include "sigproc.h" |
| 35 | + #include <assert.h> |
| 36 | + |
| 37 | + /* This is only to be used for writing. When reading, |
| 38 | +@@ -587,6 +588,17 @@ fhandler_pipe::fixup_after_fork (HANDLE parent) |
| 39 | + ReleaseMutex (hdl_cnt_mtx); |
| 40 | + } |
| 41 | + |
| 42 | ++void |
| 43 | ++fhandler_pipe::fixup_after_exec () |
| 44 | ++{ |
| 45 | ++ /* Set read pipe itself always non-blocking for cygwin process. |
| 46 | ++ Blocking/non-blocking is simulated in raw_read(). For write |
| 47 | ++ pipe, follow is_nonblocking(). */ |
| 48 | ++ bool mode = get_device () == FH_PIPEW ? is_nonblocking () : true; |
| 49 | ++ set_pipe_non_blocking (mode); |
| 50 | ++ fhandler_base::fixup_after_exec (); |
| 51 | ++} |
| 52 | ++ |
| 53 | + int |
| 54 | + fhandler_pipe::dup (fhandler_base *child, int flags) |
| 55 | + { |
| 56 | +@@ -1370,3 +1382,54 @@ close_proc: |
| 57 | + HeapFree (GetProcessHeap (), 0, shi); |
| 58 | + return NULL; |
| 59 | + } |
| 60 | ++ |
| 61 | ++void |
| 62 | ++fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout, |
| 63 | ++ int fileno_stderr) |
| 64 | ++{ |
| 65 | ++ bool need_send_noncygchld_sig = false; |
| 66 | ++ |
| 67 | ++ /* spawn_worker() is called from spawn.cc only when non-cygwin app |
| 68 | ++ is started. Set pipe mode blocking for the non-cygwin process. */ |
| 69 | ++ int fd; |
| 70 | ++ cygheap_fdenum cfd (false); |
| 71 | ++ while ((fd = cfd.next ()) >= 0) |
| 72 | ++ if (cfd->get_dev () == FH_PIPEW |
| 73 | ++ && (fd == fileno_stdout || fd == fileno_stderr)) |
| 74 | ++ { |
| 75 | ++ fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; |
| 76 | ++ pipe->set_pipe_non_blocking (false); |
| 77 | ++ |
| 78 | ++ /* Setup for query_ndl stuff. Read the comment below. */ |
| 79 | ++ if (pipe->request_close_query_hdl ()) |
| 80 | ++ need_send_noncygchld_sig = true; |
| 81 | ++ } |
| 82 | ++ else if (cfd->get_dev () == FH_PIPER && fd == fileno_stdin) |
| 83 | ++ { |
| 84 | ++ fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; |
| 85 | ++ pipe->set_pipe_non_blocking (false); |
| 86 | ++ } |
| 87 | ++ |
| 88 | ++ /* If multiple writers including non-cygwin app exist, the non-cygwin |
| 89 | ++ app cannot detect pipe closure on the read side when the pipe is |
| 90 | ++ created by system account or the pipe creator is running as service. |
| 91 | ++ This is because query_hdl which is held in write side also is a read |
| 92 | ++ end of the pipe, so the pipe is still alive for the non-cygwin app |
| 93 | ++ even after the reader is closed. |
| 94 | ++ |
| 95 | ++ To avoid this problem, let all processes in the same process |
| 96 | ++ group close query_hdl using internal signal __SIGNONCYGCHLD when |
| 97 | ++ non-cygwin app is started. */ |
| 98 | ++ if (need_send_noncygchld_sig) |
| 99 | ++ { |
| 100 | ++ tty_min dummy_tty; |
| 101 | ++ dummy_tty.ntty = (fh_devices) myself->ctty; |
| 102 | ++ dummy_tty.pgid = myself->pgid; |
| 103 | ++ tty_min *t = cygwin_shared->tty.get_cttyp (); |
| 104 | ++ if (!t) /* If tty is not allocated, use dummy_tty instead. */ |
| 105 | ++ t = &dummy_tty; |
| 106 | ++ /* Emit __SIGNONCYGCHLD to let all processes in the |
| 107 | ++ process group close query_hdl. */ |
| 108 | ++ t->kill_pgrp (__SIGNONCYGCHLD); |
| 109 | ++ } |
| 110 | ++} |
| 111 | +diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h |
| 112 | +index 649a431..15b19f7 100644 |
| 113 | +--- a/winsup/cygwin/local_includes/fhandler.h |
| 114 | ++++ b/winsup/cygwin/local_includes/fhandler.h |
| 115 | +@@ -1212,6 +1212,7 @@ public: |
| 116 | + int open (int flags, mode_t mode = 0); |
| 117 | + bool open_setup (int flags); |
| 118 | + void fixup_after_fork (HANDLE); |
| 119 | ++ void fixup_after_exec (); |
| 120 | + int dup (fhandler_base *child, int); |
| 121 | + void set_close_on_exec (bool val); |
| 122 | + int close (); |
| 123 | +@@ -1273,6 +1274,8 @@ public: |
| 124 | + } |
| 125 | + return false; |
| 126 | + } |
| 127 | ++ static void spawn_worker (int fileno_stdin, int fileno_stdout, |
| 128 | ++ int fileno_stderr); |
| 129 | + }; |
| 130 | + |
| 131 | + #define CYGWIN_FIFO_PIPE_NAME_LEN 47 |
| 132 | +diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc |
| 133 | +index 383f5e5..acdef49 100644 |
| 134 | +--- a/winsup/cygwin/spawn.cc |
| 135 | ++++ b/winsup/cygwin/spawn.cc |
| 136 | +@@ -607,38 +607,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, |
| 137 | + int fileno_stderr = 2; |
| 138 | + |
| 139 | + if (!iscygwin ()) |
| 140 | +- { |
| 141 | +- bool need_send_sig = false; |
| 142 | +- int fd; |
| 143 | +- cygheap_fdenum cfd (false); |
| 144 | +- while ((fd = cfd.next ()) >= 0) |
| 145 | +- if (cfd->get_dev () == FH_PIPEW |
| 146 | +- && (fd == fileno_stdout || fd == fileno_stderr)) |
| 147 | +- { |
| 148 | +- fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; |
| 149 | +- pipe->set_pipe_non_blocking (false); |
| 150 | +- if (pipe->request_close_query_hdl ()) |
| 151 | +- need_send_sig = true; |
| 152 | +- } |
| 153 | +- else if (cfd->get_dev () == FH_PIPER && fd == fileno_stdin) |
| 154 | +- { |
| 155 | +- fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; |
| 156 | +- pipe->set_pipe_non_blocking (false); |
| 157 | +- } |
| 158 | +- |
| 159 | +- if (need_send_sig) |
| 160 | +- { |
| 161 | +- tty_min dummy_tty; |
| 162 | +- dummy_tty.ntty = (fh_devices) myself->ctty; |
| 163 | +- dummy_tty.pgid = myself->pgid; |
| 164 | +- tty_min *t = cygwin_shared->tty.get_cttyp (); |
| 165 | +- if (!t) /* If tty is not allocated, use dummy_tty instead. */ |
| 166 | +- t = &dummy_tty; |
| 167 | +- /* Emit __SIGNONCYGCHLD to let all processes in the |
| 168 | +- process group close query_hdl. */ |
| 169 | +- t->kill_pgrp (__SIGNONCYGCHLD); |
| 170 | +- } |
| 171 | +- } |
| 172 | ++ fhandler_pipe::spawn_worker (fileno_stdin, fileno_stdout, |
| 173 | ++ fileno_stderr); |
| 174 | + |
| 175 | + bool no_pcon = mode != _P_OVERLAY && mode != _P_WAIT; |
| 176 | + term_spawn_worker.setup (iscygwin (), handle (fileno_stdin, false), |
0 commit comments