1.7.8: write fails with EAGAIN

Corinna Vinschen corinna-cygwin@cygwin.com
Mon Mar 7 17:32:00 GMT 2011

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.


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

More information about the Cygwin-developers mailing list