From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7868) id 88709385840C; Mon, 13 Dec 2021 10:40:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 88709385840C Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Takashi Yano To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: pipe: Adopt FILE_SYNCHRONOUS_IO_NONALERT flag for read pipe. X-Act-Checkin: newlib-cygwin X-Git-Author: Takashi Yano X-Git-Refname: refs/heads/master X-Git-Oldrev: f3d719c694f824fcec99ebbe88de8a5fa0a25a71 X-Git-Newrev: 9e4d308cd592fe383dec58ea6523c1b436888ef8 Message-Id: <20211213104001.88709385840C@sourceware.org> Date: Mon, 13 Dec 2021 10:40:01 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Dec 2021 10:40:01 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=9e4d308cd592fe383dec58ea6523c1b436888ef8 commit 9e4d308cd592fe383dec58ea6523c1b436888ef8 Author: Takashi Yano Date: Wed Nov 10 21:47:09 2021 +0900 Cygwin: pipe: Adopt FILE_SYNCHRONOUS_IO_NONALERT flag for read pipe. - With this patch, FILE_SYNCHRONOUS_IO_NONALERT flag is applied to the read pipe so that native C# programs work with cygwin pipe. To handle signals in reading pipe with this flag set, the read pipe itself is always set to nonblocking mode and simulates the blocking behaviour in raw_read(). - Default to byte mode rather than message mode in order to make C# programs work with cygwin pipe. Addresses: https://cygwin.com/pipermail/cygwin/2021-March/247987.html Diff: --- winsup/cygwin/fhandler_pipe.cc | 72 ++++++++++++++++-------------------------- winsup/cygwin/globals.cc | 2 +- 2 files changed, 28 insertions(+), 46 deletions(-) diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc index 5195b2807..40fb2349a 100644 --- a/winsup/cygwin/fhandler_pipe.cc +++ b/winsup/cygwin/fhandler_pipe.cc @@ -90,7 +90,10 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode, int64_t uniq_id) set_ino (uniq_id); set_unique_id (uniq_id | !!(mode & GENERIC_WRITE)); if (opened_properly) - set_pipe_non_blocking (is_nonblocking ()); + /* Set read pipe always nonblocking to allow signal handling + even with FILE_SYNCHRONOUS_IO_NONALERT. */ + set_pipe_non_blocking (get_device () == FH_PIPER ? + true : is_nonblocking ()); return 1; } @@ -264,9 +267,9 @@ fhandler_pipe::release_select_sem (const char *from) if (get_dev () == FH_PIPER) /* Number of select() and writer */ n_release = get_obj_handle_count (select_sem) - get_obj_handle_count (read_mtx); - else /* Number of select() call */ + else /* Number of select() call and reader */ n_release = get_obj_handle_count (select_sem) - - get_obj_handle_count (hdl_cnt_mtx); + - get_obj_handle_count (get_handle ()); debug_printf("%s(%s) release %d", from, get_dev () == FH_PIPER ? "PIPER" : "PIPEW", n_release); if (n_release) @@ -279,7 +282,6 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) size_t nbytes = 0; NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK io; - HANDLE evt; if (!len) return; @@ -307,60 +309,27 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) len = (size_t) -1; return; } - - if (!(evt = CreateEvent (NULL, false, false, NULL))) - { - __seterrno (); - len = (size_t) -1; - ReleaseMutex (read_mtx); - return; - } - while (nbytes < len) { ULONG_PTR nbytes_now = 0; ULONG len1 = (ULONG) (len - nbytes); - waitret = WAIT_OBJECT_0; - ResetEvent (evt); FILE_PIPE_LOCAL_INFORMATION fpli; status = NtQueryInformationFile (get_handle (), &io, &fpli, sizeof (fpli), FilePipeLocalInformation); if (NT_SUCCESS (status)) { - if (fpli.ReadDataAvailable == 0 && nbytes != 0) - break; + if (fpli.ReadDataAvailable == 0 && nbytes != 0) + break; } else if (nbytes != 0) break; - status = NtReadFile (get_handle (), evt, NULL, NULL, &io, ptr, + status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, ptr, len1, NULL, NULL); - if (status == STATUS_PENDING) - { - waitret = cygwait (evt, INFINITE, cw_cancel | cw_sig); - /* If io.Status is STATUS_CANCELLED after CancelIo, IO has actually - been cancelled and io.Information contains the number of bytes - processed so far. - Otherwise IO has been finished regulary and io.Status contains - valid success or error information. */ - CancelIo (get_handle ()); - if (waitret == WAIT_SIGNALED && io.Status != STATUS_CANCELLED) - waitret = WAIT_OBJECT_0; - - if (waitret == WAIT_CANCELED) - status = STATUS_THREAD_CANCELED; - else if (waitret == WAIT_SIGNALED) - status = STATUS_THREAD_SIGNALED; - else - status = io.Status; - } if (isclosed ()) /* A signal handler might have closed the fd. */ { - if (waitret == WAIT_OBJECT_0) - set_errno (EBADF); - else - __seterrno (); + set_errno (EBADF); nbytes = (size_t) -1; } else if (NT_SUCCESS (status) @@ -393,7 +362,16 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) nbytes = (size_t) -1; break; } - fallthrough; + waitret = cygwait (select_sem, 1); + if (waitret == WAIT_CANCELED) + pthread::static_cancel_self (); + else if (waitret == WAIT_SIGNALED) + { + set_errno (EINTR); + nbytes = (size_t) -1; + break; + } + continue; default: __seterrno_from_nt_status (status); nbytes = (size_t) -1; @@ -406,7 +384,6 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) break; } ReleaseMutex (read_mtx); - CloseHandle (evt); if (status == STATUS_THREAD_SIGNALED && nbytes == 0) { set_errno (EINTR); @@ -990,9 +967,12 @@ nt_create (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE &r, HANDLE &w, npfsh, sa_ptr->lpSecurityDescriptor); timeout.QuadPart = -500000; + /* Set FILE_SYNCHRONOUS_IO_NONALERT flag so that native + C# programs work with cygwin pipe. */ status = NtCreateNamedPipeFile (&r, access, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_CREATE, 0, pipe_type, + FILE_CREATE, + FILE_SYNCHRONOUS_IO_NONALERT, pipe_type, FILE_PIPE_BYTE_STREAM_MODE, 0, 1, psize, psize, &timeout); @@ -1104,7 +1084,9 @@ fhandler_pipe::fcntl (int cmd, intptr_t arg) const bool was_nonblocking = is_nonblocking (); int res = fhandler_base::fcntl (cmd, arg); const bool now_nonblocking = is_nonblocking (); - if (now_nonblocking != was_nonblocking) + /* Do not set blocking mode for read pipe to allow signal handling + even with FILE_SYNCHRONOUS_IO_NONALERT. */ + if (now_nonblocking != was_nonblocking && get_device () != FH_PIPER) set_pipe_non_blocking (now_nonblocking); return res; } diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index 48fb312de..ac5ad0307 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -69,7 +69,7 @@ int NO_COPY dynamically_loaded; /* Some CYGWIN environment variable variables. */ bool allow_glob = true; bool ignore_case_with_glob; -bool pipe_byte; +bool pipe_byte = true; /* Default to byte mode so that C# programs work. */ bool reset_com; bool wincmdln; winsym_t allow_winsymlinks = WSYM_default;