From 1f8962d23d3a2e5f23d64ea931bc0dc4c0e335fd Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 18 Jan 2009 16:40:50 +0200 Subject: [PATCH] Revert "Improve Win32 poll replacement (and fix #1949)" et al Looks like Winsock events operate in a weird and barely adaptable way. Fixes #2369. This reverts commit c6ea17a3ce7e5884c323a66bd48f09f551dbb86d. This reverts commit 1a582db112f0d898f93bdcc618e06d75ff8f2410. This reverts commit 8bda7d7287446b0f5b54fe69c07d600cb0bbd1a2. This reverts commit acade544006e80a73facb152fa53437e21a99a2f. --- src/network/poll.c | 111 +++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/src/network/poll.c b/src/network/poll.c index 5590b36a21..f6f9050eff 100644 --- a/src/network/poll.c +++ b/src/network/poll.c @@ -1,7 +1,7 @@ /***************************************************************************** * poll.c: I/O event multiplexing ***************************************************************************** - * Copyright © 2007-2008 Rémi Denis-Courmont + * Copyright © 2007 Rémi Denis-Courmont * $Id$ * * Author: Rémi Denis-Courmont @@ -28,7 +28,7 @@ #include #include -#ifndef WIN32 +#ifdef HAVE_POLL struct pollfd; int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout) @@ -36,80 +36,73 @@ int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout) (void)fds; (void)nfds; (void)timeout; abort (); } -#else +#else /* !HAVE_POLL */ #include #include #include int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout) { - WSAEVENT phEvents[nfds]; - DWORD val; - - vlc_testcancel (); + fd_set rdset, wrset, exset; + struct timeval tv = { 0, 0 }; + int val = -1; + FD_ZERO (&rdset); + FD_ZERO (&wrset); + FD_ZERO (&exset); for (unsigned i = 0; i < nfds; i++) { - long events = FD_CLOSE; + int fd = fds[i].fd; + if (val < fd) + 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. + * + * With BeOS, the situation is unknown (FIXME: document). + */ if (fds[i].events & POLLIN) - events |= FD_READ | FD_ACCEPT; + FD_SET (fd, &rdset); if (fds[i].events & POLLOUT) - events |= FD_WRITE; + FD_SET (fd, &wrset); if (fds[i].events & POLLPRI) - events |= FD_OOB; - fds[i].revents = 0; - - phEvents[i] = WSACreateEvent (); - WSAEventSelect (fds[i].fd, phEvents[i], events); + FD_SET (fd, &exset); } - int ret = 0, n = 0; - - switch (WaitForMultipleObjectsEx (nfds, phEvents, FALSE, timeout, TRUE)) + if (timeout >= 0) { - case WAIT_IO_COMPLETION: - WSASetLastError (WSAEINTR); - ret = -1; - break; - case WAIT_TIMEOUT: - ret = 0; - break; - default: - for (unsigned i = 0; i < nfds; i++) - { - WSANETWORKEVENTS events; - if (WSAEnumNetworkEvents (fds[i].fd, phEvents[i], &events)) - { - fds[i].revents |= POLLNVAL; - ret = -1; - continue; - } - if (events.lNetworkEvents & FD_CLOSE) - fds[i].revents |= POLLHUP | (fds[i].events & POLLIN); - if (events.lNetworkEvents & FD_ACCEPT) - fds[i].revents |= POLLIN; - if (events.lNetworkEvents & FD_OOB) - fds[i].revents |= POLLPRI; - if (events.lNetworkEvents & FD_READ) - fds[i].revents |= POLLIN; - if (events.lNetworkEvents & FD_WRITE) - { - fds[i].revents |= POLLOUT; - if (events.iErrorCode[FD_WRITE_BIT]) - fds[i].revents |= POLLERR; - } - if (fds[i].revents) - n++; - } - if (ret == 0) - ret = n; + div_t d = div (timeout, 1000); + tv.tv_sec = d.quot; + tv.tv_usec = d.rem * 1000; } - for (unsigned i = 0; i < nfds; i++) - WSACloseEvent (phEvents[i]); - vlc_testcancel (); + val = select (val + 1, &rdset, &wrset, &exset, + (timeout >= 0) ? &tv : NULL); + if (val == -1) + return -1; - return ret; + 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); + } + return val; } -#endif /* WIN32 */ +#endif /* !HAVE_POLL */ -- 2.39.5