[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