1.7.8: write fails with EAGAIN

Christopher Faylor cgf-use-the-mailinglist-please@cygwin.com
Mon Mar 7 20:35:00 GMT 2011


On Mon, Mar 07, 2011 at 06:31:42PM +0100, Corinna Vinschen wrote:
>On Mar  7 12:10, Christopher Faylor wrote:
>> On Mon, Mar 07, 2011 at 11:38:49AM -0500, Christopher Faylor wrote:
>> >Actually, in this case, it looks like the problem is that Windows
>> >doesn't like sending a huge buffer to a pipe.  The errno in this case
>> >should probably be something like EFBIG rather than EAGAIN.
>> >
>> >Does git deal with this type of errno gracefully or does it just abort
>> >if the write() fails for any reason?  I'd rather just fail and let the
>> >caller deal with it than complicate Cygwin's code by trying to loop
>> >writing smaller amount of data to the pipe so I'd prefer just changing
>> >the errno if that solves the problem.
>> 
>> Answering my own question: No, git doesn't make any useful decisions based
>> on the errno.  So, just returning a different errno is not going to make
>> this work.
>> 
>> So, my options are to:
>> 
>> 1) Limit the buffer size to some value like 64 mib and expect the caller to
>> deal with that.
>> 
>> 2) Limit the buffer size to some value like 64 mib and loop in
>> fhandler_overlapped::write_overlapped until everything has been written.
>> 
>> 3) Attempt the WriteFile(), notice the error condition and then do 1) or 2).
>> 
>> 2) or 3) would be the most like Linux.  1) is by far the easiest and would
>> probably solve the current git error case.
>> 
>> Just thinking out loud here.  I think I've convinced myself that I should
>> go with 3 + 2.
>
>SUSv4 is quite helpful when it comes to writing on pipes:
>
> * Write requests of {PIPE_BUF} bytes or less shall not be interleaved
>   with data from other processes doing writes on the same pipe.
>   Writes of greater than {PIPE_BUF} bytes may have data interleaved,
>   on arbitrary boundaries, with writes by other processes, whether or
>   not the O_NONBLOCK flag of the file status flags is set.
> * If the O_NONBLOCK flag is clear, a write request may cause the
>   thread to block, but on normal completion it shall return nbyte.
> * If the O_NONBLOCK flag is set, write() requests shall be handled
>   differently, in the following ways:
>      + The write() function shall not block the thread.
>      + A write request for {PIPE_BUF} or fewer bytes shall have the
>	following effect: if there is sufficient space available in
>	the pipe, write() shall transfer all the data and return the
>	number of bytes requested. Otherwise, write() shall transfer
>	no data and return -1 with errno set to [EAGAIN].
>      + A write request for more than {PIPE_BUF} bytes shall cause one
>	of the following:
>	   o When at least one byte can be written, transfer what it
>	     can and return the number of bytes written. When all data
>	     previously written to the pipe is read, it shall transfer
>	     at least {PIPE_BUF} bytes.
>	   o When no data can be written, transfer no data, and return
>	     -1 with errno set to [EAGAIN].
>
>So, a blocking write with many bytes is not expected to be atomic
>anyway, and if the pipe is non-blocking you may write (and return) any
>number of bytes which happen to fit.

None of the above is really what I was worried about.  I was worried
about preserving non-blocking behavior if possible.

cgf



More information about the Cygwin-developers mailing list