Re: [PATCH] mingw: handle writes to non-blocking pipe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi René,

On Wed, 10 Aug 2022, 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.

Excellent analysis, thank you!

However, let's reword this to clarify that the error code is set to EAGAIN
only if the buffer-sized partial write fails.

>
> Helped-by: Jeff King <peff@xxxxxxxx>
> Signed-off-by: René Scharfe <l.s.r@xxxxxx>
> ---
>  compat/mingw.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/compat/mingw.c b/compat/mingw.c
> index b5502997e2..c6f244c0fe 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> @@ -689,6 +689,8 @@ int mingw_fflush(FILE *stream)
>  	return ret;
>  }
>
> +#define PIPE_BUFFER_SIZE (8192)

This constant hails all the way back from 897bb8cb2c2 (Windows: A pipe()
replacement whose ends are not inherited to children., 2007-12-07), in
case anyone wondered like I did where that number came from (and why it is
so low).

It is outside the purview of this patch to change that constant, therefore
I am fine with leaving this as-is.

> +
>  #undef write
>  ssize_t mingw_write(int fd, const void *buf, size_t len)
>  {
> @@ -702,6 +704,21 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
>  		else
>  			errno = EINVAL;
>  	}
> +	if (result < 0 && errno == ENOSPC) {

It might make the code clearer to turn this into an `else if`.

> +		/* 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);

It is probably easier to reason about to recurse instead of using a `goto`
here.

Thank you for this patch!
Dscho

> +			errno = EAGAIN;
> +		}
> +	}
>
>  	return result;
>  }
> @@ -1079,7 +1096,7 @@ int pipe(int filedes[2])
>  	HANDLE h[2];
>
>  	/* this creates non-inheritable handles */
> -	if (!CreatePipe(&h[0], &h[1], NULL, 8192)) {
> +	if (!CreatePipe(&h[0], &h[1], NULL, PIPE_BUFFER_SIZE)) {
>  		errno = err_win_to_posix(GetLastError());
>  		return -1;
>  	}
> --
> 2.37.1.windows.1
>

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux