From: Gabriele Svelto 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 #include +#include #include #include #include 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 #include +#include #include #include #include @@ -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 23a8f4f3f3..b2c206d775 100644 --- a/modules/video_capture/linux/video_capture_linux.cc +++ b/modules/video_capture/linux/video_capture_linux.cc @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc index 7a70c2ff88..00cede01cb 100644 --- a/modules/video_capture/linux/video_capture_v4l2.cc +++ b/modules/video_capture/linux/video_capture_v4l2.cc @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -20,6 +20,14 @@ #include #include #include +// v4l includes +#if defined(__NetBSD__) || defined(__OpenBSD__) // WEBRTC_BSD +#include +#elif defined(__sun) +#include +#else +#include +#endif #include #include @@ -405,16 +413,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, NULL, NULL, &timeout); + retVal = poll(&rSet, 1, 1000); { MutexLock lock(&capture_lock_); @@ -424,12 +429,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; }