Skip to content

Insufficient delay in UInput._find_device_fallback() #214

Open

Description

@arpruss

On my Raspberry PI 3B+, when I create a uinput device using a non-root user, the device does not show up quickly enough for UInput._find_device_fallback() to find it. (It works fine with root, oddly.) Currently there is a sleep(0.1) delay in the method. If I raise the delay to sleep(0.5), it works fine.

But one doesn't want to add latency to everybody's code. So what I did on my local installation was to add a timeout of 10 seconds, and loop until the time runs out if nothing is found, with a 0.1 second delay after each try. This also removes the 0.1 second delay on systems where the device shows up quickly.

Activity

  1. sezanzeb commented on Mar 11, 2024

    @sezanzeb
    Collaborator

    what's your kernel version? uname -r

    And please also post cat /boot/config-$(uname -r) | ack CONFIG_DEVTMPFS

  2. sezanzeb commented on Mar 11, 2024

    @sezanzeb
    Collaborator

    And mount | grep /dev

  3. arpruss commented on Mar 11, 2024

    @arpruss
    Author
    pi@raspberrypi:~ $ uname -r
    5.15.84-v7+
    pi@raspberrypi:~ $ cat /boot/config-$(uname -r) | ack CONFIG_DEVTMPFS
    cat: /boot/config-5.15.84-v7+: No such file or directory
    pi@raspberrypi:~ $ mount | grep /dev
    /dev/mmcblk0p2 on / type ext4 (rw,noatime)
    devtmpfs on /dev type devtmpfs (rw,relatime,size=347696k,nr_inodes=86924,mode=755)
    tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
    devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
    cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
    mqueue on /dev/mqueue type mqueue (rw,relatime)
    /dev/mmcblk0p1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
    
    
  4. arpruss commented on Mar 11, 2024

    @arpruss
    Author

    Also:

    pi@raspberrypi:~ $ sudo modprobe configs
    pi@raspberrypi:~ $ zcat /proc/config.gz  | ack CONFIG_DEVTMPFS
    CONFIG_DEVTMPFS=y
    CONFIG_DEVTMPFS_MOUNT=y
    
  5. sezanzeb commented on Mar 11, 2024

    @sezanzeb
    Collaborator

    Interesting, so it takes some time even though devtmpfs is being used. If I remember correctly, this contradicts our previous discussion @KarsMulder

  6. arpruss commented on Mar 11, 2024

    @arpruss
    Author

    On general principles, I also think it's not ideal to rely on the delay, as it can result in code breaking on a heavily loaded system, or when running under emulation, or when the system is severely underclocked, etc. I think the ideal would be a caller-specifiable timeout, with a generous default.

  7. KarsMulder commented on Mar 11, 2024

    @KarsMulder
    Contributor

    I might of course have been wrong and devtmpfs might after all not actually be in charge of managing event device nodes, just some other kind of device nodes.

    Another possibility to consider is that the event nodes do actually show up immediately through devtmpfs, but are only accessible to root, because devtmpfs always creates nodes with a fixed set of default permissions and it is the task of udev to change those permissions to whatever the OS wants them to be (source.) So maybe the device shows up immediately owned by root:root, and 0.1~0.5 seconds later udev notices that a device has shown up and chowns it to root:input, making it readable to the user that the script is running at.

    This could be an explanation for why it immediately shows up when running as root, but not when running as non-root. Though if that was the case, I would expect the UInput() call to fail with PermissionError getting thrown instead of merely failing to find the device.

  8. arpruss commented on Mar 11, 2024

    @arpruss
    Author

    Good guess about permissions. I included os.system("ls -l /dev/input") during each iteration of the retry loop in my modified version. First time through it showed

    total 0
    drwxr-xr-x  2 root root      80 Mar 11 18:36 by-id
    drwxr-xr-x  2 root root      80 Mar 11 18:36 by-path
    crw-rw----+ 1 root input 13, 64 Mar  9 23:28 event0
    crw-rw----+ 1 root input 13, 65 Mar 11 18:36 event1
    crw-------  1 root root  13, 66 Mar 11 18:50 event2
    crw-rw----+ 1 root input 13,  0 Mar 11 18:36 js0
    crw-rw----  1 root input 13,  1 Mar 11 18:50 js1
    crw-rw----  1 root input 13, 63 Mar  9 20:17 mice
    

    Note the lack of group permissions for event2. Second time around it showed:

    total 0
    drwxr-xr-x  2 root root      80 Mar 11 18:36 by-id
    drwxr-xr-x  2 root root      80 Mar 11 18:36 by-path
    crw-rw----+ 1 root input 13, 64 Mar  9 23:28 event0
    crw-rw----+ 1 root input 13, 65 Mar 11 18:36 event1
    crw-rw----  1 root input 13, 66 Mar 11 18:50 event2
    crw-rw----+ 1 root input 13,  0 Mar 11 18:36 js0
    crw-rw----  1 root input 13,  1 Mar 11 18:50 js1
    crw-rw----  1 root input 13, 63 Mar  9 20:17 mice
    

    Now event2 is accessible.

    So this does indeed explain why it works as root but not as an ordinary user.

  9. arpruss commented on Mar 12, 2024

    @arpruss
    Author

    A workaround is for the module caller to loop until the device becomes available. But it would be neater if the fix was in the evdev module.

  10. KarsMulder commented on Mar 12, 2024

    @KarsMulder
    Contributor

    I have created pull request #215 to fix this issue.

  11. arpruss commented on Mar 13, 2024

    @arpruss
    Author

    It works for me! Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions