xremap: --watch not working due to permission denied error

First, thank you for this awesome tool!

I’ve tried the --watch option, and it doesn’t seem to work as intended on my machine. I’ve forked the repo and added a few println! statements to understand what’s going on, so here’s what I did to reproduce the issue with the forked version:

  1. Start ./target/release/xremap --watch /path/to/config.yml. So far, everything’s working as intended: It correctly detects /dev/event3 as my keyboard. This is the output:

    Path "/dev/input/event4" cannot be opened: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }
    Selecting devices from the following list:
    ------------------------------------------------------------------------------
    /dev/input/event0 : Power Button
    /dev/input/event1 : Power Button
    /dev/input/event2 : USB Keyboard Consumer Control
    /dev/input/event3 : USB Keyboard
    /dev/input/event5 : UVC Camera (046d:0825)
    /dev/input/event6 : PixArt USB Optical Mouse
    /dev/input/event7 : HDA ATI HDMI HDMI/DP,pcm=3
    /dev/input/event8 : HDA ATI HDMI HDMI/DP,pcm=7
    /dev/input/event9 : HDA ATI HDMI HDMI/DP,pcm=8
    /dev/input/event10: HDA ATI HDMI HDMI/DP,pcm=9
    /dev/input/event11: HDA ATI HDMI HDMI/DP,pcm=10
    /dev/input/event12: HDA ATI HDMI HDMI/DP,pcm=11
    /dev/input/event13: HD-Audio Generic Front Mic
    /dev/input/event14: HD-Audio Generic Rear Mic
    /dev/input/event15: HD-Audio Generic Line
    /dev/input/event16: HD-Audio Generic Line Out Front
    /dev/input/event17: HD-Audio Generic Line Out Surround
    /dev/input/event18: HD-Audio Generic Line Out CLFE
    /dev/input/event19: HD-Audio Generic Front Headphone
    /dev/input/event20: BurrBrown from Texas Instruments USB AUDIO  CODEC
    /dev/input/event21: USB Keyboard System Control
    ------------------------------------------------------------------------------
    Selected keyboards automatically since --device options weren't specified:
    ------------------------------------------------------------------------------
    /dev/input/event3 : USB Keyboard
    ------------------------------------------------------------------------------
    Received events from inotify: Err(EAGAIN)
    
  2. Disconnect the keyboard. This is the output:

    Received events from inotify: Ok([InotifyEvent { wd: WatchDescriptor { wd: 1 },
    mask: IN_ATTRIB, cookie: 0, name: Some("event3") }])
    Detected device changes. Reselecting devices.
    Path "/dev/input/event2" cannot be opened: Os { code: 13, kind:
    PermissionDenied, message: "Permission denied" }
    Selecting devices from the following list:
    ------------------------------------------------------------------------------
    /dev/input/event0 : Power Button
    /dev/input/event1 : Power Button
    /dev/input/event5 : UVC Camera (046d:0825)
    /dev/input/event6 : PixArt USB Optical Mouse
    /dev/input/event7 : HDA ATI HDMI HDMI/DP,pcm=3
    /dev/input/event8 : HDA ATI HDMI HDMI/DP,pcm=7
    /dev/input/event9 : HDA ATI HDMI HDMI/DP,pcm=8
    /dev/input/event10: HDA ATI HDMI HDMI/DP,pcm=9
    /dev/input/event11: HDA ATI HDMI HDMI/DP,pcm=10
    /dev/input/event12: HDA ATI HDMI HDMI/DP,pcm=11
    /dev/input/event13: HD-Audio Generic Front Mic
    /dev/input/event14: HD-Audio Generic Rear Mic
    /dev/input/event15: HD-Audio Generic Line
    /dev/input/event16: HD-Audio Generic Line Out Front
    /dev/input/event17: HD-Audio Generic Line Out Surround
    /dev/input/event18: HD-Audio Generic Line Out CLFE
    /dev/input/event19: HD-Audio Generic Front Headphone
    /dev/input/event20: BurrBrown from Texas Instruments USB AUDIO  CODEC
    /dev/input/event21: USB Keyboard System Control
    ------------------------------------------------------------------------------
    Selected keyboards automatically since --device options weren't specified:
    ------------------------------------------------------------------------------
    warning: No device was selected, but --watch is waiting for new devices.
    ------------------------------------------------------------------------------
    
  3. Reconnect the keyboard. Notice that in the output, event2 and event3 (the keyboard) cannot be opened (PermissionDenied).

    Received events from inotify: Ok([InotifyEvent { wd: WatchDescriptor { wd: 1 }, mask: IN_CREATE, cookie: 0, name: Some("event3") }, InotifyEvent { wd: WatchDescriptor { wd: 1 }, mask: IN_ATTRIB, cookie: 0, name: Some("event3") }])
    Detected device changes. Reselecting devices.
    Path "/dev/input/event21" cannot be opened: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }
    Path "/dev/input/event4" cannot be opened: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }
    Path "/dev/input/event2" cannot be opened: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }
    Path "/dev/input/event3" cannot be opened: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }
    Selecting devices from the following list:
    ------------------------------------------------------------------------------
    /dev/input/event0 : Power Button
    /dev/input/event1 : Power Button
    /dev/input/event5 : UVC Camera (046d:0825)
    /dev/input/event6 : PixArt USB Optical Mouse
    /dev/input/event7 : HDA ATI HDMI HDMI/DP,pcm=3
    /dev/input/event8 : HDA ATI HDMI HDMI/DP,pcm=7
    /dev/input/event9 : HDA ATI HDMI HDMI/DP,pcm=8
    /dev/input/event10: HDA ATI HDMI HDMI/DP,pcm=9
    /dev/input/event11: HDA ATI HDMI HDMI/DP,pcm=10
    /dev/input/event12: HDA ATI HDMI HDMI/DP,pcm=11
    /dev/input/event13: HD-Audio Generic Front Mic
    /dev/input/event14: HD-Audio Generic Rear Mic
    /dev/input/event15: HD-Audio Generic Line
    /dev/input/event16: HD-Audio Generic Line Out Front
    /dev/input/event17: HD-Audio Generic Line Out Surround
    /dev/input/event18: HD-Audio Generic Line Out CLFE
    /dev/input/event19: HD-Audio Generic Front Headphone
    /dev/input/event20: BurrBrown from Texas Instruments USB AUDIO  CODEC
    ------------------------------------------------------------------------------
    Selected keyboards automatically since --device options weren't specified:
    ------------------------------------------------------------------------------
    warning: No device was selected, but --watch is waiting for new devices.
    ------------------------------------------------------------------------------
    

So to my understanding, this is a race condition where the USB device is not yet readable immediately after the inotify event. According to the inotify println! statements that I’ve added, we receive an IN_ATTRIB event in addition to the IN_CREATE event when the device is reconnected. So apparently, even after the first IN_ATTRIB event, the device is still not readable.

I ran notifywait -r -m /dev/input | grep 'event3' to see what events occur after the keyboard is connected, here’s the output:

/dev/input/ CREATE event3
/dev/input/ ATTRIB event3
/dev/input/ OPEN event3
/dev/input/ CLOSE_NOWRITE,CLOSE event3
/dev/input/ OPEN event3
/dev/input/ ATTRIB event3
/dev/input/ ATTRIB event3
/dev/input/ ATTRIB event3
/dev/input/ CLOSE_NOWRITE,CLOSE event3
/dev/input/ OPEN event3
/dev/input/ CLOSE_WRITE,CLOSE event3
/dev/input/ OPEN event3
/dev/input/ CLOSE_WRITE,CLOSE event3
/dev/input/ OPEN event3
/dev/input/ MODIFY event3

I really have no idea why I get so many ATTRIB events, and why it closes the file multiple times after the device has been connected. But those are definitely the events that occur after the device has been connected.

A simple workaround is to just sleep for 100 milliseconds before listing the files in /dev/input, but perhaps there’s a more elegant fix.

If you can’t reproduce this issue on your machine, I’m happy to help, let me know if you want me test any patches.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 19 (12 by maintainers)

Most upvoted comments

Thank you for confirming it. I’m glad to hear that this problem is now gone. The new version has been released as v0.3.0.