This is the mail archive of the
cygwin-developers
mailing list for the Cygwin project.
Re: 1.7.8: write fails with EAGAIN
- From: Corinna Vinschen <corinna-cygwin at cygwin dot com>
- To: cygwin-developers at cygwin dot com
- Date: Mon, 7 Mar 2011 18:31:42 +0100
- Subject: Re: 1.7.8: write fails with EAGAIN
- References: <4D72992D.4090007@tweerlei.de> <20110307103951.GL6393@calimero.vinschen.de> <20110307153708.GA2538@ednor.casa.cgf.cx> <20110307163849.GA26824@ednor.casa.cgf.cx> <20110307171045.GA26028@ednor.casa.cgf.cx>
- Reply-to: cygwin-developers at cygwin dot com
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
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Project Co-Leader cygwin AT cygwin DOT com
Red Hat