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_linux.cc  |  1 +
 .../video_capture/linux/device_info_v4l2.cc   | 16 +++++-----
 .../linux/video_capture_linux.cc              |  1 +
 .../video_capture/linux/video_capture_v4l2.cc | 29 +++++++++++--------
 4 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/modules/video_capture/linux/device_info_linux.cc b/modules/video_capture/linux/device_info_linux.cc
index 56da475bf3..cae63c7c2d 100644
--- a/modules/video_capture/linux/device_info_linux.cc
+++ b/modules/video_capture/linux/device_info_linux.cc
@@ -10,6 +10,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/modules/video_capture/linux/device_info_v4l2.cc b/modules/video_capture/linux/device_info_v4l2.cc
index f77d791033..a2435bcd4f 100644
--- a/modules/video_capture/linux/device_info_v4l2.cc
+++ b/modules/video_capture/linux/device_info_v4l2.cc
@@ -12,6 +12,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.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_linux.cc b/modules/video_capture/linux/video_capture_linux.cc
index 1c635ea440..7872662fae 100644
--- a/modules/video_capture/linux/video_capture_linux.cc
+++ b/modules/video_capture/linux/video_capture_linux.cc
@@ -10,6 +10,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/ioctl.h>
diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc
index 243656e782..882928dcbb 100644
--- a/modules/video_capture/linux/video_capture_v4l2.cc
+++ b/modules/video_capture/linux/video_capture_v4l2.cc
@@ -12,7 +12,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/videodev2.h>
+#include <poll.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/ioctl.h>
@@ -20,6 +20,14 @@
 #include <sys/select.h>
 #include <time.h>
 #include <unistd.h>
+// v4l includes
+#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 <new>
 #include <string>
@@ -411,16 +419,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_);
@@ -430,12 +435,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;
     }
