Source code

Revision control

Copy as Markdown

Other Tools

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.
---
.../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 1cb83f82d5..b8af09a7aa 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>
@@ -417,16 +424,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_);
@@ -436,12 +440,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;
}