From 9a3705f82dbf30d9706e8a0b76fc6164cf3ba4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 4 Feb 2018 22:45:28 +0100 Subject: [PATCH 1/3] evdev: Fix select() call It's not guaranteed that the eventfd is smaller than the monitor fd, because fds are not always monotonically allocated. To select() correctly in all cases, use the max between the monitor fd and eventfd. --- Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp index 85e4973270..398d33eb78 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp @@ -72,7 +72,7 @@ static void HotplugThreadFunc() FD_SET(monitor_fd, &fds); FD_SET(s_wakeup_eventfd, &fds); - int ret = select(monitor_fd + 1, &fds, nullptr, nullptr, nullptr); + int ret = select(std::max(monitor_fd, s_wakeup_eventfd) + 1, &fds, nullptr, nullptr, nullptr); if (ret < 1 || !FD_ISSET(monitor_fd, &fds)) continue; From 0822bb347d12c97cb9bb307f624d6f8a8ed1cf06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 4 Feb 2018 22:48:38 +0100 Subject: [PATCH 2/3] evdev: Don't leak eventfd on shutdown --- Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp index 398d33eb78..6e4aab495d 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp @@ -136,6 +136,7 @@ static void StopHotplugThread() { } s_hotplug_thread.join(); + close(s_wakeup_eventfd); } void Init() From 6a93223283bd0d2bef8ce9c29f5043ade49a6831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 5 Feb 2018 00:59:07 +0100 Subject: [PATCH 3/3] evdev: Always unref received udev devices Whenever udev_monitor_receive_device() returns a non-null pointer, the device must be unref'd after use with udev_device_unref(). We previously missed some unref calls for non-evdev devices. --- .../Core/InputCommon/ControllerInterface/evdev/evdev.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp index 6e4aab495d..2049c85237 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp @@ -76,10 +76,11 @@ static void HotplugThreadFunc() if (ret < 1 || !FD_ISSET(monitor_fd, &fds)) continue; - udev_device* dev = udev_monitor_receive_device(monitor); + std::unique_ptr dev{ + udev_monitor_receive_device(monitor), udev_device_unref}; - const char* action = udev_device_get_action(dev); - const char* devnode = udev_device_get_devnode(dev); + const char* action = udev_device_get_action(dev.get()); + const char* devnode = udev_device_get_devnode(dev.get()); if (!devnode) continue; @@ -107,7 +108,6 @@ static void HotplugThreadFunc() s_devnode_name_map.insert(std::pair(devnode, name)); } } - udev_device_unref(dev); } NOTICE_LOG(SERIALINTERFACE, "evdev hotplug thread stopped"); }