]> git.sesse.net Git - vlc/blobdiff - src/network/poll.c
Maemo: work-around segmentation fault when poll() unwinds
[vlc] / src / network / poll.c
index 3fb441319c1ea1d2d1a9b2cafa64f82929a4aad3..eb97c83db07749449b3dfac987ff927a6bf089fe 100644 (file)
 # include "config.h"
 #endif
 
-#include <vlc/vlc.h>
-
-#ifndef HAVE_POLL
-#include <string.h>
+#include <vlc_common.h>
 #include <stdlib.h>
 #include <vlc_network.h>
 
-int poll (struct pollfd *fds, unsigned nfds, int timeout)
+
+#if HAVE_MAEMO
+# include <signal.h>
+# include <errno.h>
+# include <poll.h>
+
+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 <string.h>
+
+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);
@@ -48,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)
@@ -58,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);
@@ -66,7 +138,18 @@ int poll (struct pollfd *fds, unsigned nfds, int timeout)
     }
 
     val = select (val + 1, &rdset, &wrset, &exset,
-                  (timeout >= 0) ? &tv : NULL);
+                  /*(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;