This is the mail archive of the
cygwin-developers
mailing list for the Cygwin project.
Re: 1.7.8: write fails with EAGAIN
- From: Christopher Faylor <cgf-use-the-mailinglist-please at cygwin dot com>
- To: cygwin-developers at cygwin dot com
- Date: Mon, 7 Mar 2011 15:35:14 -0500
- 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> <20110307173142.GB12899@calimero.vinschen.de>
- Reply-to: cygwin-developers at cygwin dot com
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