From: Gabriele Svelto <gsvelto@mozilla.com>
Date: Mon, 28 Oct 2019 23:26:00 +0000
Subject: Bug 1590984 - Use poll() instead of select() in WebRTC code r=drno

The use of select() was leading to crashes when the file descriptor value was
larger than FD_SETSIZE. Recent versions of glibc have checks in the FD_CLR(),
FD_SET() and FD_ISSET() macros that will abort() the program instead of doing
an out-of-bounds access. poll() doesn't have limitations on the file
descriptor values and provides behavior that is otherwise identical to
select() thus solving the problem.

Differential Revision: https://phabricator.services.mozilla.com/D50798
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/59fb6760bb6785a6f8a51be6fc66bf04cfba3e16
---
 .../video_capture/linux/device_info_v4l2.cc   | 16 +++++-------
 .../video_capture/linux/video_capture_v4l2.cc | 26 +++++++++++--------
 2 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/modules/video_capture/linux/device_info_v4l2.cc b/modules/video_capture/linux/device_info_v4l2.cc
index fa930d8020..5c228772ab 100644
--- a/modules/video_capture/linux/device_info_v4l2.cc
+++ b/modules/video_capture/linux/device_info_v4l2.cc
@@ -18,6 +18,7 @@
 #else
 #include <linux/videodev2.h>
 #endif
+#include <poll.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
 
@@ -91,16 +92,13 @@ void DeviceInfoV4l2::HandleEvent(inotify_event* event, int fd)
 
 int DeviceInfoV4l2::EventCheck(int fd)
 {
-    struct timeval timeout;
-    fd_set rfds;
+    struct pollfd fds = {
+      .fd = fd,
+      .events = POLLIN,
+      .revents = 0
+    };
 
-    timeout.tv_sec = 0;
-    timeout.tv_usec = 100000;
-
-    FD_ZERO(&rfds);
-    FD_SET(fd, &rfds);
-
-    return select(fd+1, &rfds, NULL, NULL, &timeout);
+    return poll(&fds, 1, 100);
 }
 
 int DeviceInfoV4l2::HandleEvents(int fd)
diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc
index bef2939ce6..03e3d9c7cc 100644
--- a/modules/video_capture/linux/video_capture_v4l2.cc
+++ b/modules/video_capture/linux/video_capture_v4l2.cc
@@ -11,7 +11,14 @@
 #include "modules/video_capture/linux/video_capture_v4l2.h"
 
 #include <fcntl.h>
+#if defined(__NetBSD__) || defined(__OpenBSD__) // WEBRTC_BSD
+#include <sys/videoio.h>
+#elif defined(__sun)
+#include <sys/videodev2.h>
+#else
 #include <linux/videodev2.h>
+#endif
+#include <poll.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/select.h>
@@ -416,16 +423,13 @@ bool VideoCaptureModuleV4L2::CaptureProcess() {
   RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
 
   int retVal = 0;
-  fd_set rSet;
-  struct timeval timeout;
+  struct pollfd rSet;
 
-  FD_ZERO(&rSet);
-  FD_SET(_deviceFd, &rSet);
-  timeout.tv_sec = 1;
-  timeout.tv_usec = 0;
+  rSet.fd = _deviceFd;
+  rSet.events = POLLIN;
+  rSet.revents = 0;
 
-  // _deviceFd written only in StartCapture, when this thread isn't running.
-  retVal = select(_deviceFd + 1, &rSet, nullptr, nullptr, &timeout);
+  retVal = poll(&rSet, 1, 1000);
 
   {
     MutexLock lock(&capture_lock_);
@@ -435,12 +439,12 @@ bool VideoCaptureModuleV4L2::CaptureProcess() {
     }
 
     if (retVal < 0 && errno != EINTR) {  // continue if interrupted
-      // select failed
+      // poll failed
       return false;
     } else if (retVal == 0) {
-      // select timed out
+      // poll timed out
       return true;
-    } else if (!FD_ISSET(_deviceFd, &rSet)) {
+    } else if (!(rSet.revents & POLLIN)) {
       // not event on camera handle
       return true;
     }
