Am 10.08.2022 um 22:02 schrieb Jeff King: > On Wed, Aug 10, 2022 at 07:39:40AM +0200, René Scharfe wrote: > >> write() on Windows reports ENOSPC when writing to a non-blocking pipe >> whose buffer is full and rejects writes bigger than the buffer outright. >> Change the error code to EAGAIN and try a buffer-sized partial write to >> comply with POSIX and the expections of our Git-internal callers. > > Bearing in mind that I have no qualifications for reviewing > Windows-specific patches, this seems like the right thing to be doing > from the behavior you saw. > > One question: > >> + if (result < 0 && errno == ENOSPC) { >> + /* check if fd is a non-blocking pipe */ >> + HANDLE h = (HANDLE) _get_osfhandle(fd); >> + DWORD s; >> + if (GetFileType(h) == FILE_TYPE_PIPE && >> + GetNamedPipeHandleState(h, &s, NULL, NULL, NULL, NULL, 0) && >> + (s & PIPE_NOWAIT)) { >> + DWORD obuflen; >> + if (!GetNamedPipeInfo(h, NULL, &obuflen, NULL, NULL)) >> + obuflen = PIPE_BUFFER_SIZE; >> + if (len > obuflen) >> + return mingw_write(fd, buf, obuflen); >> + errno = EAGAIN; >> + } > > OK, so we call GetNamedPipeInfo() to find the size of the pipe buffer. > It's unclear to me from Microsoft's docs if that is the _total_ size, or > if it's the remaining available size. Hopefully the latter, since none > of this works otherwise. ;) > > But two corner cases: > > - If we fail to get the size, we guess that it's the maximum. Is this > dangerous? I'm not sure why the call would fail, but if for some > reason it did fail and we can't make forward progress, would we > enter an infinite recursion of mingw_write()? Would it be safer to > bail with EAGAIN in such a case (through granted, that probably just > puts us into an infinite loop in xwrite())? AFAIU it's the total size, not the available space. I think I confused it with PIPE_BUF, which we should use instead. Alternatively we could retry with ever smaller sizes, down to one byte, to avoid EAGAIN as much as possible. Sounds costly, though. > > - According to the docs: > > If the buffer size is zero, the buffer is allocated as needed. > > If we see this case, we'd then call mingw_write() with 0 bytes, > which I imagine also makes no forward progress (though maybe we > eventually return a successful 0-byte write?). Ah, yes, forgot that case. René