[vlc-commits] commit: Win32: fix poll() with more than 64 sockets ( =?UTF-8?Q?R=C3=A9mi=20Denis=2DCourmont=20?=)

git at videolan.org git at videolan.org
Wed Nov 24 21:59:44 CET 2010


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Nov 24 22:52:57 2010 +0200| [1a0ad6c1ab6a0ffc3994be4b42db3f0924bc46e6] | committer: Rémi Denis-Courmont 

Win32: fix poll() with more than 64 sockets

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=1a0ad6c1ab6a0ffc3994be4b42db3f0924bc46e6
---

 src/network/poll.c |   73 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/src/network/poll.c b/src/network/poll.c
index 41ed1b8..35192ce 100644
--- a/src/network/poll.c
+++ b/src/network/poll.c
@@ -70,23 +70,37 @@ int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
     (void)fds; (void)nfds; (void)timeout;
     abort ();
 }
-#else /* !HAVE_POLL */
+
+#elif defined (WIN32)
 
 #include <string.h>
+#include <errno.h>
 
 int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
 {
-    fd_set rdset, wrset, exset;
+    size_t setsize = sizeof (fd_set) + (nfds - FD_SETSIZE) * sizeof (SOCKET);
+    fd_set *rdset = malloc (setsize);
+    fd_set *wrset = malloc (setsize);
+    fd_set *exset = malloc (setsize);
     struct timeval tv = { 0, 0 };
     int val;
 
+    if (unlikely(rdset == NULL || wrset == NULL || exset == NULL))
+    {
+        free (rdset);
+        free (wrset);
+        free (exset);
+        errno = ENOMEM;
+        return -1;
+    }
+
 resume:
     val = -1;
     vlc_testcancel ();
 
-    FD_ZERO (&rdset);
-    FD_ZERO (&wrset);
-    FD_ZERO (&exset);
+    FD_ZERO (rdset);
+    FD_ZERO (wrset);
+    FD_ZERO (exset);
     for (unsigned i = 0; i < nfds; i++)
     {
         int fd = fds[i].fd;
@@ -94,23 +108,22 @@ resume:
             val = fd;
 
         /* With POSIX, FD_SET & FD_ISSET are not defined if fd is negative or
-	 * bigger or equal than FD_SETSIZE. That is one of the reasons why VLC
-	 * uses poll() rather than select(). Most POSIX systems implement
-	 * fd_set has a bit field with no sanity checks. This is especially bad
-	 * on systems (such as BSD) that have no process open files limit by
-	 * default, such that it is quite feasible to get fd >= FD_SETSIZE.
-	 * The next instructions will result in a buffer overflow if run on
-	 * a POSIX system, and the later FD_ISSET will do undefined memory
-	 * access.
-	 *
-	 * With Winsock, fd_set is a table of integers. This is awfully slow.
-	 * However, FD_SET and FD_ISSET silently and safely discard
-	 * overflows. If it happens we will loose socket events. Note that
-	 * most (if not all) Winsock SOCKET handles are actually bigger than
-	 * FD_SETSIZE in terms of absolute value - they are not POSIX file
-	 * descriptors. From Vista, there is a much nicer WSAPoll(), but Mingw
-	 * is yet to support it.
-	 */
+         * bigger or equal than FD_SETSIZE. That is one of the reasons why VLC
+         * uses poll() rather than select(). Most POSIX systems implement
+         * fd_set has a bit field with no sanity checks. This is especially bad
+         * on systems (such as BSD) that have no process open files limit by
+         * default, such that it is quite feasible to get fd >= FD_SETSIZE.
+         * The next instructions will result in a buffer overflow if run on
+         * a POSIX system, and the later FD_ISSET would perform an undefined
+         * memory read.
+         *
+         * With Winsock, fd_set is a table of integers. This is awfully slow.
+         * However, FD_SET and FD_ISSET silently and safely discard excess
+         * entries. Here, overflow cannot happen anyway: fd_set of adequate
+         * size are allocated.
+         * Note that Vista has a much nicer WSAPoll(), but Mingw does not
+         * support it yet.
+         */
         if (fds[i].events & POLLIN)
             FD_SET ((SOCKET)fd, rdset);
         if (fds[i].events & POLLOUT)
@@ -135,7 +148,7 @@ resume:
         tv.tv_usec = d.rem * 1000;
     }
 
-    val = select (val + 1, &rdset, &wrset, &exset,
+    val = select (val + 1, rdset, wrset, exset,
                   /*(timeout >= 0) ?*/ &tv /*: NULL*/);
 
 #ifndef HAVE_ALERTABLE_SELECT
@@ -154,10 +167,16 @@ resume:
     for (unsigned i = 0; i < nfds; i++)
     {
         int fd = fds[i].fd;
-        fds[i].revents = (FD_ISSET (fd, &rdset) ? POLLIN : 0)
-                       | (FD_ISSET (fd, &wrset) ? POLLOUT : 0)
-                       | (FD_ISSET (fd, &exset) ? POLLPRI : 0);
+        fds[i].revents = (FD_ISSET (fd, rdset) ? POLLIN : 0)
+                       | (FD_ISSET (fd, wrset) ? POLLOUT : 0)
+                       | (FD_ISSET (fd, exset) ? POLLPRI : 0);
     }
+    free (exset);
+    free (wrset);
+    free (rdset);
     return val;
 }
-#endif /* !HAVE_POLL */
+
+#else
+# error poll() not implemented!
+#endif



More information about the vlc-commits mailing list