This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] poll() return value is actually that of select()


bug example src: http://pastebin.com/f719e4c11

First off... I've been happily using Cygwin for years, glad I finally
have a patch to contribute...Thanks!

While testing some socket code on Cygwin and Linux, I noticed the
returns from poll() were always twice what they were on Linux when a
socket had been closed remotely and then polled().

>From  'man 2 poll' on debian:

"On success, a positive number is returned; this is the number of
structures which have non-zero revents fields (in other words, those
descriptors  with  events  or errors  reported).   A  value  of 0
indicates that the call timed out and no file descriptors were ready.
On error, -1 is returned, and errno is set appropriately."

Digging deeper, I found that Cygwin's poll() is implemented with
cygwin_select(), and thus returns the total number of ISSET events,
instead of just the number of fds with events. Thus, the behavior is:

 "On  success,  select()  and  pselect() return the number of file
descriptors contained in the three returned descriptor sets (that is,
the total number  of  bits that  are  set  in readfds, writefds,
exceptfds) which may be zero if the timeout expires before anything
interesting happens.  On error, -1 is returned, and errno is  set
appropriately;  the sets and timeout become undefined, so do not rely
on their contents after an error."

Attached is some goo which makes poll() work as expected.... compiled,
tested, works... fyi, as of 9:30am EST string.h broke the build, i had
to roll it back.

-craig

--------
2007-12-12  Craig MacGregor  <cmacgreg@gmail.com>

	* poll.cc (poll): Return count of fds with events instead of total event count

Index: cygwin/poll.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/poll.cc,v
retrieving revision 1.48
diff -u -p -r1.48 poll.cc
--- cygwin/poll.cc      31 Jul 2006 14:27:56 -0000      1.48
+++ cygwin/poll.cc      12 Dec 2007 13:29:53 -0000
@@ -76,15 +76,18 @@ poll (struct pollfd *fds, nfds_t nfds, i
   if (invalid_fds)
     return invalid_fds;

-  int ret = cygwin_select (max_fd + 1, read_fds, write_fds,
except_fds, timeout < 0 ? NULL : &tv);
+  int ret = cygwin_select (max_fd + 1, read_fds, write_fds,
except_fds, timeout < 0 ? NULL : &tv);
+
+  int ir = 0, ret_p = 0;
+    /* Count fds in ISSETs for return, but just once each */

   if (ret > 0)
-    for (unsigned int i = 0; i < nfds; ++i)
+    for (unsigned int i = 0; i < nfds; ret_p+=ir, ir = 0, ++i)
       {
        if (fds[i].fd >= 0)
          {
            if (cygheap->fdtab.not_open (fds[i].fd))
-             fds[i].revents = POLLHUP;
+             ir = 1, fds[i].revents = POLLHUP;
            else
              {
                fhandler_socket *sock;
@@ -98,22 +101,23 @@ poll (struct pollfd *fds, nfds_t nfds, i
                     will return -1 with errno set to the appropriate value."
                     So it looks like there's actually no good reason to
                     return POLLERR. */
-                 fds[i].revents |= POLLIN;
+                 ir = 1, fds[i].revents |= POLLIN;
                /* Handle failed connect. */
                if (FD_ISSET(fds[i].fd, write_fds)
                    && (sock = cygheap->fdtab[fds[i].fd]->is_socket ())
                    && sock->connect_state () == connect_failed)
-                 fds[i].revents |= (POLLIN | POLLERR);
+                 ir = 1, fds[i].revents |= (POLLIN | POLLERR);
                else
                  {
                    if (FD_ISSET(fds[i].fd, write_fds))
-                     fds[i].revents |= POLLOUT;
+                     ir = 1, fds[i].revents |= POLLOUT;
                    if (FD_ISSET(fds[i].fd, except_fds))
-                     fds[i].revents |= POLLPRI;
+                     ir = 1, fds[i].revents |= POLLPRI;
                  }
              }
-         }
+         }
+
       }

-  return ret;
+  return !ret_p ? ret : ret_p;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]