Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorTakashi Yano <takashi.yano@nifty.ne.jp>2021-11-10 15:47:09 +0300
committerTakashi Yano <takashi.yano@nifty.ne.jp>2021-12-12 16:11:05 +0300
commit9e4d308cd592fe383dec58ea6523c1b436888ef8 (patch)
treebf9eb608749d0d9588fa102c2470761952b36f4c /winsup
parentf3d719c694f824fcec99ebbe88de8a5fa0a25a71 (diff)
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
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/fhandler_pipe.cc72
-rw-r--r--winsup/cygwin/globals.cc2
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;