diff --git a/plugins/linux-v4l2/v4l2-udev.c b/plugins/linux-v4l2/v4l2-udev.c index 8394b6276..67a50af86 100644 --- a/plugins/linux-v4l2/v4l2-udev.c +++ b/plugins/linux-v4l2/v4l2-udev.c @@ -15,6 +15,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include +#include +#include #include #include @@ -40,6 +43,7 @@ static pthread_mutex_t udev_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_t udev_thread; static os_event_t *udev_event; +static int udev_event_fd; static signal_handler_t *udev_signalhandler = NULL; @@ -108,8 +112,6 @@ static void *udev_event_thread(void *vptr) UNUSED_PARAMETER(vptr); int fd; - fd_set fds; - struct timeval tv; struct udev *udev; struct udev_monitor *mon; struct udev_device *dev; @@ -127,12 +129,14 @@ static void *udev_event_thread(void *vptr) fd = udev_monitor_get_fd(mon); while (os_event_try(udev_event) == EAGAIN) { - FD_ZERO(&fds); - FD_SET(fd, &fds); - tv.tv_sec = 1; - tv.tv_usec = 0; + struct pollfd fds[2]; - if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) + fds[0].fd = fd; + fds[0].events = POLLIN; + fds[1].fd = udev_event_fd; + fds[1].events = POLLIN; + + if (poll(fds, 2, 1000) <= 0) continue; dev = udev_monitor_receive_device(mon); @@ -158,13 +162,19 @@ void v4l2_init_udev(void) if (udev_refs == 0) { if (os_event_init(&udev_event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; - if (pthread_create(&udev_thread, NULL, udev_event_thread, - NULL) != 0) + if ((udev_event_fd = eventfd(0, EFD_CLOEXEC)) < 0) goto fail; + if (pthread_create(&udev_thread, NULL, udev_event_thread, + NULL) != 0) { + close(udev_event_fd); + goto fail; + } udev_signalhandler = signal_handler_create(); - if (!udev_signalhandler) + if (!udev_signalhandler) { + close(udev_event_fd); goto fail; + } signal_handler_add_array(udev_signalhandler, udev_signals); } udev_refs++; @@ -180,8 +190,10 @@ void v4l2_unref_udev(void) /* unref udev monitor */ if (udev_refs && --udev_refs == 0) { os_event_signal(udev_event); + eventfd_write(udev_event_fd, 1); pthread_join(udev_thread, NULL); os_event_destroy(udev_event); + close(udev_event_fd); if (udev_signalhandler) signal_handler_destroy(udev_signalhandler);