diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc index 7a5cefb3d..5b6b98892 100644 --- a/winsup/cygwin/fhandler_pipe.cc +++ b/winsup/cygwin/fhandler_pipe.cc @@ -222,6 +222,7 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) DWORD waitret = WAIT_OBJECT_0; bool keep_looping = false; size_t orig_len = len; + size_t total_len = 0; if (!len) return; @@ -236,29 +237,37 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) do { - len = orig_len; + char *ptr1 = (char *) ptr + total_len; + len = orig_len - total_len; keep_looping = false; if (evt) ResetEvent (evt); - if (!is_nonblocking ()) + + FILE_PIPE_LOCAL_INFORMATION fpli; + ULONG reader_count; + ULONG max_len = 64; + + WaitForSingleObject (read_mtx, INFINITE); + + /* Make sure never to request more bytes than half the pipe + buffer size. Every pending read lowers WriteQuotaAvailable + on the write side and thus affects select's ability to return + more or less reliable info whether a write succeeds or not. + + Let the size of the request depend on the number of readers + at the time. */ + status = NtQueryInformationFile (get_handle (), &io, + &fpli, sizeof (fpli), + FilePipeLocalInformation); + if (NT_SUCCESS (status) && fpli.ReadDataAvailable == 0) { - FILE_PIPE_LOCAL_INFORMATION fpli; - ULONG reader_count; - ULONG max_len = 64; - - WaitForSingleObject (read_mtx, INFINITE); - - /* Make sure never to request more bytes than half the pipe - buffer size. Every pending read lowers WriteQuotaAvailable - on the write side and thus affects select's ability to return - more or less reliable info whether a write succeeds or not. - - Let the size of the request depend on the number of readers - at the time. */ - status = NtQueryInformationFile (get_handle (), &io, - &fpli, sizeof (fpli), - FilePipeLocalInformation); - if (NT_SUCCESS (status) && fpli.ReadDataAvailable == 0) + if (total_len != 0) + { + len = total_len; + ReleaseMutex (read_mtx); + break; + } + if (!is_nonblocking ()) { reader_count = get_obj_handle_count (get_handle ()); if (reader_count < 10) @@ -267,10 +276,11 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) len = max_len; } } - status = NtReadFile (get_handle (), evt, NULL, NULL, &io, ptr, + + status = NtReadFile (get_handle (), evt, NULL, NULL, &io, ptr1, len, NULL, NULL); - if (!is_nonblocking ()) - ReleaseMutex (read_mtx); + ReleaseMutex (read_mtx); + if (evt && status == STATUS_PENDING) { waitret = cygwait (evt); @@ -291,9 +301,11 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) } else if (NT_SUCCESS (status)) { - len = io.Information; - if (len == 0) + total_len += io.Information; + if (total_len < orig_len) keep_looping = true; + else + len = total_len; } else { @@ -308,9 +320,11 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) case STATUS_MORE_ENTRIES: case STATUS_BUFFER_OVERFLOW: /* `io.Information' is supposedly valid. */ - len = io.Information; - if (len == 0) + total_len += io.Information; + if (total_len < orig_len) keep_looping = true; + else + len = total_len; break; case STATUS_PIPE_LISTENING: case STATUS_PIPE_EMPTY: