[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