Skip to content

Commit

Permalink
#197 Using timeouts for calls to the daemon in key-mapper-control
Browse files Browse the repository at this point in the history
  • Loading branch information
sezanzeb committed Nov 4, 2021
1 parent f9e7ef1 commit 1d79ad3
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 15 deletions.
6 changes: 4 additions & 2 deletions bin/key-mapper-control
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,12 @@ def communicate(options, daemon):
# if device was specified, autoload for that one. if None autoload
# for all devices.
if options.device is None:
daemon.autoload()
# timeout is not documented, for more info see
# https://github.com/LEW21/pydbus/blob/master/pydbus/proxy_method.py
daemon.autoload(timeout=10)
else:
group = require_group()
daemon.autoload_single(group.key)
daemon.autoload_single(group.key, timeout=2)

if options.command == START:
group = require_group()
Expand Down
7 changes: 7 additions & 0 deletions data/99-key-mapper.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# helpful commands:
# udevadm monitor --property
# udevadm info --query=all --name=/dev/input/event3
# to test changes:
# sudo udevadm control --reload-rules
# journalctl -f
ACTION=="add", SUBSYSTEM=="input", RUN+="/bin/key-mapper-control --command autoload --device $env{DEVNAME}"
3 changes: 0 additions & 3 deletions data/key-mapper.rules

This file was deleted.

17 changes: 16 additions & 1 deletion keymapper/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ def may_autoload(self, group_key, preset):
return False


def remove_timeout(func):
"""Remove timeout to ensure the call works if the daemon is not a proxy."""
# the timeout kwarg is a feature of pydbus. This is needed to make tests work
# that create a Daemon by calling its constructor instead of using pydbus.
def wrapped(*args, **kwargs):
if "timeout" in kwargs:
del kwargs["timeout"]

return func(*args, **kwargs)

return wrapped


class Daemon:
"""Starts injecting keycodes based on the configuration.
Expand Down Expand Up @@ -150,7 +163,7 @@ def __init__(self):

self.config_dir = None

if USER != 'root':
if USER != "root":
self.set_config_dir(get_config_path())

self.autoload_history = AutoloadHistory()
Expand Down Expand Up @@ -326,6 +339,7 @@ def _autoload(self, group_key):
self.start_injecting(group.key, preset)
self.autoload_history.remember(group.key, preset)

@remove_timeout
def autoload_single(self, group_key):
"""Inject the configured autoload preset for the device.
Expand Down Expand Up @@ -353,6 +367,7 @@ def autoload_single(self, group_key):

self._autoload(group_key)

@remove_timeout
def autoload(self):
"""Load all autoloaded presets for the current config_dir.
Expand Down
10 changes: 7 additions & 3 deletions keymapper/injection/injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,15 +409,19 @@ def run(self):
# stopped event loop most likely
pass
except OSError as error:
logger.error(str(error))
logger.error("Failed to run injector coroutines: %s", str(error))

if len(coroutines) > 0:
# expected when stop_injecting is called,
# during normal operation as well as tests this point is not
# reached otherwise.
logger.debug("asyncio coroutines ended")
logger.debug("Injector coroutines ended")

for source in sources:
# ungrab at the end to make the next injection process not fail
# its grabs
source.ungrab()
try:
source.ungrab()
except OSError as error:
# it might have disappeared
logger.debug("OSError for ungrab on %s: %s", source.path, str(error))
4 changes: 2 additions & 2 deletions readme/pylint.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def make_lang():
('/usr/lib/systemd/system', ['data/key-mapper.service']),
('/etc/dbus-1/system.d/', ['data/keymapper.Control.conf']),
('/etc/xdg/autostart/', ['data/key-mapper-autoload.desktop']),
('/usr/lib/udev/rules.d', ['data/key-mapper.rules']),
('/usr/lib/udev/rules.d', ['data/99-key-mapper.rules']),
('/usr/bin/', ['bin/key-mapper-gtk']),
('/usr/bin/', ['bin/key-mapper-service']),
('/usr/bin/', ['bin/key-mapper-control']),
Expand Down
6 changes: 3 additions & 3 deletions tests/testcases/test_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,15 +222,15 @@ def test_daemon(self):
self.assertEqual(event.value, 1)

def test_config_dir(self):
config.set('foo', 'bar')
self.assertEqual(config.get('foo'), 'bar')
config.set("foo", "bar")
self.assertEqual(config.get("foo"), "bar")

# freshly loads the config and therefore removes the previosly added key.
# This is important so that if the service is started via sudo or pkexec
# it knows where to look for configuration files.
self.daemon = Daemon()
self.assertEqual(self.daemon.config_dir, get_config_path())
self.assertIsNone(config.get('foo'))
self.assertIsNone(config.get("foo"))

def test_refresh_on_start(self):
if os.path.exists(get_config_path("xmodmap.json")):
Expand Down

0 comments on commit 1d79ad3

Please sign in to comment.