From d6744fbc4eb5b3a8d7dd8f4a3cc4348f576d6878 Mon Sep 17 00:00:00 2001 From: Josh Bendavid <Josh.Bendavid@cern.ch> Date: Thu, 26 Dec 2019 13:06:57 -0500 Subject: [PATCH] Fix handling of symlinked device descriptors in keyboard_remote and move remaining sync io to executor thread pool (#30206) * fix handling of symlinked device decriptors * make check for symlinked paths more efficient * make variable names pylint compliant * move sync io during setup and device connect/disconnect to executor thread pool * move remaining sync io during setup to executor thread pool * remove unnecessary lambda functions --- .../components/keyboard_remote/__init__.py | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/keyboard_remote/__init__.py b/homeassistant/components/keyboard_remote/__init__.py index 24889a3f820..310bd0189bd 100644 --- a/homeassistant/components/keyboard_remote/__init__.py +++ b/homeassistant/components/keyboard_remote/__init__.py @@ -2,6 +2,7 @@ # pylint: disable=import-error import asyncio import logging +import os import aionotify from evdev import InputDevice, categorize, ecodes, list_devices @@ -119,9 +120,11 @@ class KeyboardRemote: # add initial devices (do this AFTER starting watcher in order to # avoid race conditions leading to missing device connections) initial_start_monitoring = set() - descriptors = list_devices(DEVINPUT) + descriptors = await self.hass.async_add_executor_job(list_devices, DEVINPUT) for descriptor in descriptors: - dev, handler = self.get_device_handler(descriptor) + dev, handler = await self.hass.async_add_executor_job( + self.get_device_handler, descriptor + ) if handler is None: continue @@ -165,6 +168,15 @@ class KeyboardRemote: handler = self.handlers_by_descriptor[descriptor] elif dev.name in self.handlers_by_name: handler = self.handlers_by_name[dev.name] + else: + # check for symlinked paths matching descriptor + for test_descriptor, test_handler in self.handlers_by_descriptor.items(): + if test_handler.dev is not None: + fullpath = test_handler.dev.path + else: + fullpath = os.path.realpath(test_descriptor) + if fullpath == descriptor: + handler = test_handler return (dev, handler) @@ -186,7 +198,9 @@ class KeyboardRemote: (event.flags & aionotify.Flags.CREATE) or (event.flags & aionotify.Flags.ATTRIB) ) and not descriptor_active: - dev, handler = self.get_device_handler(descriptor) + dev, handler = await self.hass.async_add_executor_job( + self.get_device_handler, descriptor + ) if handler is None: continue self.active_handlers_by_descriptor[descriptor] = handler @@ -242,7 +256,7 @@ class KeyboardRemote: """Stop event monitoring task and issue event.""" if self.monitor_task is not None: try: - self.dev.ungrab() + await self.hass.async_add_executor_job(self.dev.ungrab) except OSError: pass # monitoring of the device form the event loop and closing of the @@ -272,7 +286,7 @@ class KeyboardRemote: try: _LOGGER.debug("Start device monitoring") - dev.grab() + await self.hass.async_add_executor_job(dev.grab) async for event in dev.async_read_loop(): if event.type is ecodes.EV_KEY: if event.value in self.key_values: -- GitLab