[PATCH v4.2] Cygwin: pipe: Switch pipe mode to blocking mode by defaut
Ken Brown
kbrown@cornell.edu
Tue Sep 17 18:22:22 GMT 2024
On 9/17/2024 9:49 AM, Takashi Yano wrote:
>>> @@ -439,19 +396,45 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
>>> if (!len)
>>> return 0;
>>>
>>> - if (reader_closed ())
>>> + ssize_t avail = pipe_buf_size;
>>> + bool real_non_blocking_mode = false;
>>> + if (is_nonblocking ())
>>> {
>>> - set_errno (EPIPE);
>>> - raise (SIGPIPE);
>>> - return -1;
>>> + FILE_PIPE_LOCAL_INFORMATION fpli;
>>> + status = NtQueryInformationFile (get_handle (), &io, &fpli, sizeof fpli,
>>> + FilePipeLocalInformation);
>>> + if (NT_SUCCESS (status))
>>> + {
>>> + if (fpli.WriteQuotaAvailable != 0)
>>> + avail = fpli.WriteQuotaAvailable;
>>> + else /* WriteQuotaAvailable == 0 */
>>> + { /* Refer to the comment in select.cc: pipe_data_available(). */
>>> + /* NtSetInformationFile() in set_pipe_non_blocking(true) seems
>>> + to fail with STATUS_PIPE_BUSY if the pipe is not empty.
>>> + In this case, the pipe is really full if WriteQuotaAvailable
>>> + is zero. Otherwise, the pipe is empty. */
>>> + if (!((fhandler_pipe *)this)->set_pipe_non_blocking (true))
>>> + {
>>> + /* Full */
>>> + set_errno (EAGAIN);
>>> + return -1;
>>> + }
>>> + /* Restore the pipe mode to blocking. */
>>> + ((fhandler_pipe *)this)->set_pipe_non_blocking (false);
>>> + /* Pipe should be empty because reader is waiting the data. */
>>> + }
>>> + }
>>> + else if (((fhandler_pipe *)this)->set_pipe_non_blocking (true))
>>> + /* The pipe space is unknown. */
>>> + real_non_blocking_mode = true;
>> What if set_pipe_non_blocking (true) fails. Do we really want to
>> continue, in which case we'll do a blocking write below?
> If we want to return an error for this case, what errno is appropriate,
> do you think? EIO?
This is a little tricky because there have actually been two errors if
we get to this point. I think EIO is fine except in one case: If one or
both errors are due to a broken pipe, we need to use EPIPE (and raise
SIGPIPE). This is easy to test if the first call fails. To test the
second, I guess you'd have to modify set_pipe_non_blocking so that it
checks for a broken pipe if it fails. Or maybe have it return a status
code that callers can test if they want? I'm not sure which approach is
better.
Ken
More information about the Cygwin-patches
mailing list