]> sourceware.org Git - newlib-cygwin.git/commitdiff
* select.cc (pipe_data_available): New function - uses NtQueryInformationFile
authorChristopher Faylor <me@cgf.cx>
Wed, 1 Jun 2011 00:57:49 +0000 (00:57 +0000)
committerChristopher Faylor <me@cgf.cx>
Wed, 1 Jun 2011 00:57:49 +0000 (00:57 +0000)
to return information about pipes.
(peek_pipe): Rewrite to use pipe_data_available for both read and write tests.

winsup/cygwin/ChangeLog
winsup/cygwin/select.cc

index a15ff6d00acafd7e931aa0e4b787192665b96647..d766b169b9041bb492f4433de76f06c58199d60d 100644 (file)
@@ -1,3 +1,10 @@
+2011-05-31  Christopher Faylor  <me.cygwin2011@cgf.cx>
+
+       * select.cc (pipe_data_available): New function - uses
+       NtQueryInformationFile to return information about pipes.
+       (peek_pipe): Rewrite to use pipe_data_available for both read and write
+       tests.
+
 2011-05-30  Christopher Faylor  <me.cygwin2011@cgf.cx>
 
        * dtable.cc (dtable::select_write): Add missing argument to
index 92eabcf9c10db77039f13bc2905e67adb0163ec4..14953a23a35e28f7bf4f4e97c43011577dc4868e 100644 (file)
@@ -473,26 +473,71 @@ no_verify (select_record *, fd_set *, fd_set *, fd_set *)
   return 0;
 }
 
+static int
+pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
+{
+  IO_STATUS_BLOCK iosb = {0};
+  FILE_PIPE_LOCAL_INFORMATION fpli = {0};
+
+  bool res = false;
+  if (NtQueryInformationFile (h,
+                             &iosb,
+                             &fpli,
+                             sizeof (fpli),
+                             FilePipeLocalInformation))
+    {
+      /* 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",
+                    fd, fh->get_name ());
+      res = writing ? true : -1;
+    }
+  else if (!writing)
+    {
+      res = !!fpli.ReadDataAvailable;
+      select_printf ("fd %d, %s, read avail %u", fd, fh->get_name (), fpli.ReadDataAvailable);
+    }
+  else
+    {
+      /* If there is anything available in the pipe buffer then signal
+        that.  This means that a pipe could still block since you could
+        be trying to write more to the pipe than is available in the
+        buffer but that is the hazard of select().  */
+      if ((fpli.WriteQuotaAvailable = (fpli.OutboundQuota - fpli.ReadDataAvailable)))
+       {
+         select_printf ("fd %d, %s, write: size %lu, avail %lu", fd,
+                        fh->get_name (), fpli.OutboundQuota,
+                        fpli.WriteQuotaAvailable);
+         res = true;
+       }
+      /* If we somehow inherit a tiny pipe (size < PIPE_BUF), then consider
+        the pipe writable only if it is completely empty, to minimize the
+        probability that a subsequent write will block.  */
+      else if (fpli.OutboundQuota < PIPE_BUF &&
+              fpli.WriteQuotaAvailable == fpli.OutboundQuota)
+       {
+         select_printf ("fd, %s, write tiny pipe: size %lu, avail %lu",
+                        fd, fh->get_name (), fpli.OutboundQuota,
+                        fpli.WriteQuotaAvailable);
+         res = true;
+       }
+    }
+  return res;
+}
+
 static int
 peek_pipe (select_record *s, bool from_select)
 {
   HANDLE h;
   set_handle_or_return_if_not_open (h, s);
 
-  int n = 0;
   int gotone = 0;
   fhandler_base *fh = (fhandler_base *) s->fh;
 
-  /* Don't check if this is a non-blocking fd and I/O is still active.
-     That could give a false-positive with peek_pipe and friends. */
-  if (fh->has_ongoing_io ())
-    return 0;
-
-  /* Don't perform complicated tests if we don't need to. */
-  if (!s->read_selected && !s->except_selected)
-    goto out;
-
-  if (s->read_selected)
+  DWORD dev = fh->get_device ();
+  if (s->read_selected && dev != FH_PIPEW)
     {
       if (s->read_ready)
        {
@@ -524,106 +569,37 @@ peek_pipe (select_record *s, bool from_select)
          gotone = s->read_ready = true;
          goto out;
        }
-    }
-
-  if (fh->get_device () == FH_PIPEW)
-    select_printf ("%s, select for read/except on write end of pipe",
-                  fh->get_name ());
-  else if (!PeekNamedPipe (h, NULL, 0, NULL, (DWORD *) &n, NULL))
-    switch (GetLastError ())
-      {
-      case ERROR_BAD_PIPE:
-      case ERROR_PIPE_BUSY:
-      case ERROR_NO_DATA:
-      case ERROR_PIPE_NOT_CONNECTED:
-       n = 0;
-       break;
-      default:
-       select_printf ("%s, PeekNamedPipe failed, %E", fh->get_name ());
-       n = -1;
-       break;
-      }
-
-  if (n < 0)
-    {
-      select_printf ("%s, n %d", fh->get_name (), n);
-      if (s->except_selected)
-       gotone += s->except_ready = true;
-      if (s->read_selected)
-       gotone += s->read_ready = true;
-    }
-  if (n > 0 && s->read_selected)
-    {
-      select_printf ("%s, ready for read: avail %d", fh->get_name (), n);
-      gotone += s->read_ready = true;
-    }
-  if (!gotone && s->fh->hit_eof ())
-    {
-      select_printf ("%s, saw EOF", fh->get_name ());
-      if (s->except_selected)
-       gotone += s->except_ready = true;
-      if (s->read_selected)
-       gotone += s->read_ready = true;
-    }
+      int n = pipe_data_available (s->fd, fh, h, false);
 
-out:
-  if (s->write_selected)
-    {
-      if (s->write_ready)
+      if (n < 0)
        {
-         select_printf ("%s, already ready for write", fh->get_name ());
-         gotone++;
+         select_printf ("read: %s, n %d", fh->get_name (), n);
+         if (s->except_selected)
+           gotone += s->except_ready = true;
+         if (s->read_selected)
+           gotone += s->read_ready = true;
        }
-      /* Do we need to do anything about SIGTTOU here? */
-      else if (fh->get_device () == FH_PIPER)
-       select_printf ("%s, select for write on read end of pipe",
-                      fh->get_name ());
-      else
+      else if (n > 0)
        {
-         IO_STATUS_BLOCK iosb = {0};
-         FILE_PIPE_LOCAL_INFORMATION fpli = {0};
-
-         if (NtQueryInformationFile (h,
-                                     &iosb,
-                                     &fpli,
-                                     sizeof (fpli),
-                                     FilePipeLocalInformation))
-           {
-             /* 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 ("%s, NtQueryInformationFile failed",
-                            fh->get_name ());
-             gotone += s->write_ready = true;
-           }
-         /* If there is anything available in the pipe buffer then signal
-            that.  This means that a pipe could still block since you could
-            be trying to write more to the pipe than is available in the
-            buffer but that is the hazard of select().  */
-         else if ((fpli.WriteQuotaAvailable = (fpli.OutboundQuota - fpli.ReadDataAvailable)))
-           {
-             select_printf ("%s, ready for write: size %lu, avail %lu",
-                            fh->get_name (),
-                            fpli.OutboundQuota,
-                            fpli.WriteQuotaAvailable);
-             gotone += s->write_ready = true;
-           }
-         /* If we somehow inherit a tiny pipe (size < PIPE_BUF), then consider
-            the pipe writable only if it is completely empty, to minimize the
-            probability that a subsequent write will block.  */
-         else if (fpli.OutboundQuota < PIPE_BUF &&
-                  fpli.WriteQuotaAvailable == fpli.OutboundQuota)
-           {
-             select_printf ("%s, tiny pipe: size %lu, avail %lu",
-                            fh->get_name (),
-                            fpli.OutboundQuota,
-                            fpli.WriteQuotaAvailable);
-             gotone += s->write_ready = true;
-           }
+         select_printf ("read: %s, ready for read: avail %d", fh->get_name (), n);
+         gotone += s->read_ready = true;
+       }
+      if (!gotone && s->fh->hit_eof ())
+       {
+         select_printf ("read: %s, saw EOF", fh->get_name ());
+         if (s->except_selected)
+           gotone += s->except_ready = true;
+         if (s->read_selected)
+           gotone += s->read_ready = true;
        }
     }
 
+out:
+  if (s->write_selected && dev != FH_PIPER)
+    {
+      gotone += s->write_ready =  pipe_data_available (s->fd, fh, h, true);
+      select_printf ("write: %s, gotone %d", fh->get_name (), gotone);
+    }
   return gotone;
 }
 
This page took 0.040797 seconds and 5 git commands to generate.