X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fnetwork%2Fpoll.c;h=575bb10745ef34c26bdd5c732bebb5c1a017da8e;hb=cdb6faf0d09605a6af1216b4f75872ca3de8dcdc;hp=b8b19721a2f3737ba4e459cd48bc2da06fe26d64;hpb=c0b2d638f8aaa96da3dcee62598927603fe4f843;p=vlc diff --git a/src/network/poll.c b/src/network/poll.c index b8b19721a2..575bb10745 100644 --- a/src/network/poll.c +++ b/src/network/poll.c @@ -21,19 +21,68 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#ifndef HAVE_POLL -#include +#include #include #include -int poll (struct pollfd *fds, unsigned nfds, int timeout) + +#ifdef HAVE_MAEMO +# include +# include +# include + +int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout) +{ + struct timespec tsbuf, *ts; + sigset_t set; + int canc, ret; + + if (timeout != -1) + { + div_t d = div (timeout, 1000); + tsbuf.tv_sec = d.quot; + tsbuf.tv_nsec = d.rem * 1000000; + ts = &tsbuf; + } + else + ts = NULL; + + pthread_sigmask (SIG_BLOCK, NULL, &set); + sigdelset (&set, SIGRTMIN); + + canc = vlc_savecancel (); + ret = ppoll (fds, nfds, ts, &set); + vlc_restorecancel (canc); + + vlc_testcancel (); + return ret; +} + +#elif defined (HAVE_POLL) +struct pollfd; + +int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout) +{ + (void)fds; (void)nfds; (void)timeout; + abort (); +} +#else /* !HAVE_POLL */ + +#include + +int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout) { fd_set rdset, wrset, exset; struct timeval tv = { 0, 0 }; - int val = -1; + int val; +resume: + val = -1; + vlc_testcancel (); FD_ZERO (&rdset); FD_ZERO (&wrset); @@ -44,8 +93,26 @@ int poll (struct pollfd *fds, unsigned nfds, int timeout) if (val < fd) val = fd; - /* I assume the OS has a solution select overflow if it does not have - * poll(). If it did not, we are screwed anyway. */ + /* 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) FD_SET (fd, &rdset); if (fds[i].events & POLLOUT) @@ -54,6 +121,15 @@ int poll (struct pollfd *fds, unsigned nfds, int timeout) FD_SET (fd, &exset); } +#ifndef HAVE_ALERTABLE_SELECT +# warning FIXME! Fix cancellation and remove this crap. + if ((timeout < 0) || (timeout > 50)) + { + tv.tv_sec = 0; + tv.tv_usec = 50000; + } + else +#endif if (timeout >= 0) { div_t d = div (timeout, 1000); @@ -61,17 +137,28 @@ int poll (struct pollfd *fds, unsigned nfds, int timeout) tv.tv_usec = d.rem * 1000; } - val = select (val + 1, &rdset, &wrset, NULL, - (timeout >= 0) ? &tv : NULL); + val = select (val + 1, &rdset, &wrset, &exset, + /*(timeout >= 0) ?*/ &tv /*: NULL*/); + +#ifndef HAVE_ALERTABLE_SELECT + if (val == 0) + { + if (timeout > 0) + timeout -= (timeout > 50) ? 50 : timeout; + if (timeout != 0) + goto resume; + } +#endif + if (val == -1) return -1; for (unsigned i = 0; i < nfds; i++) { int fd = fds[i].fd; - fds[i].revents = (FD_ISSET (fds[i].fd, &rdset) ? POLLIN : 0) - | (FD_ISSET (fds[i].fd, &wrset) ? POLLOUT : 0) - | (FD_ISSET (fds[i].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); } return val; }