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

Corinna Vinschen corinna-cygwin@cygwin.com
Wed Sep 15 11:13:25 GMT 2021


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;


Corinna


More information about the Cygwin-developers mailing list