cygrunsrv + sshd + rsync = 20 times too slow -- throttled?

Ken Brown kbrown@cornell.edu
Wed Sep 15 11:41:40 GMT 2021


On 9/15/2021 7:13 AM, Corinna Vinschen wrote:
> On Sep 15 19:48, Takashi Yano wrote:
>> On Wed, 15 Sep 2021 11:57:44 +0200
>> Corinna Vinschen wrote:
>>> ...but we're unconditionally using NtQueryInformationFile at the start
>>> of pipe_data_available.  If this is the read side of the pipe, isn't
>>> there a chance that another (non-Cygwin) process is performing a blocking
>>> read and this call will hang?
>>
>> I will check that.
> 
> Something like that comes to mind:
> 
> diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
> index fd23122988c3..cf9ad87538f2 100644
> --- a/winsup/cygwin/select.cc
> +++ b/winsup/cygwin/select.cc
> @@ -594,18 +594,6 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
>     if (fh->has_ongoing_io ())
>       return 0;
>   
> -  status = NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
> -				   FilePipeLocalInformation);
> -  if (!NT_SUCCESS (status))
> -    {
> -      /* If NtQueryInformationFile fails, optimistically assume the
> -	 pipe is writable.  This could happen if we somehow
> -	 inherit a pipe that doesn't permit FILE_READ_ATTRIBUTES
> -	 access on the write end.  */
> -      select_printf ("fd %d, %s, NtQueryInformationFile failed, status %y",
> -		     fd, fh->get_name (), status);
> -      return writing ? 1 : -1;
> -    }
>     if (writing)
>       {
>         /* If there is anything available in the pipe buffer then signal
> @@ -633,6 +621,18 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
>         /* Note: Do not use NtQueryInformationFile() for query_hdl because
>   	 NtQueryInformationFile() seems to interfere with reading pipes
>   	 in non-cygwin apps. Instead, use PeekNamedPipe() here. */
> +      status = NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
> +				       FilePipeLocalInformation);
> +      if (!NT_SUCCESS (status))
> +	{
> +	  /* If NtQueryInformationFile fails, optimistically assume the
> +	     pipe is writable.  This could happen if we somehow
> +	     inherit a pipe that doesn't permit FILE_READ_ATTRIBUTES
> +	     access on the write end.  */
> +	  select_printf ("fd %d, %s, NtQueryInformationFile failed, status %y",
> +			 fd, fh->get_name (), status);
> +	  return 1;
> +	}
>         if (fh->get_device () == FH_PIPEW && fpli.WriteQuotaAvailable == 0)
>   	{
>   	  HANDLE query_hdl = ((fhandler_pipe *) fh)->get_query_handle ();
> @@ -652,11 +652,15 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
>   	}
>         /* TODO: Buffer really full or non-Cygwin reader? */
>       }
> -  else if (fpli.ReadDataAvailable)
> +  else
>       {
> -      paranoid_printf ("fd %d, %s, read avail %u", fd, fh->get_name (),
> -		       fpli.ReadDataAvailable);
> -      return 1;
> +      DWORD nbytes_in_pipe;
> +      if (PeekNamedPipe (h, NULL, 0, NULL, &nbytes_in_pipe, NULL))
> +	{
> +	  paranoid_printf ("fd %d, %s, read avail %u", fd, fh->get_name (),
> +			   nbytes_in_pipe);
> +	  return nbytes_in_pipe > 0;
> +	}
>       }
>     if (fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE)
>       return -1;

Maybe we want to call NtQueryInformationFile in all cases except FH_PIPER, 
keeping in mind that there are callers of pipe_data_available other than pipes. 
  That way we can still test for FILE_PIPE_CLOSING_STATE at the end in many cases.

Ken


More information about the Cygwin-developers mailing list