vlc | branch: master | Rémi Denis-Courmont <[email protected]> | 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 _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
