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_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 #endif +#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_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 +#if defined(__NetBSD__) || defined(__OpenBSD__) // WEBRTC_BSD +#include +#elif defined(__sun) +#include +#else #include +#endif +#include #include #include #include @@ -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; }