How to know when udev rules are done being applied to a new USB device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello.

In Linux, there seems to be a period of time when a newly-connected
USB device will be detectable by libudev, but the udev rules governing
its permissions have not been applied.  This is a problem for me
because I want to write user-mode software that waits for a USB device
to appear, and then opens a handle to it and performs I/O.  If I
connect too early, I will end up getting a permission error.
Specifically, I will get the EACCES error when I call open() on the
USB device node (e.g. /dev/bus/usb/006/041).  What is the best way to
solve this problem?  Is there any way to ask the system whether all of
the udev rules have been applied for a particular device?

If you are interested, here are the details of how to reproduce this problem:

https://gist.github.com/DavidEGrayson/1e2e6f0a7a5a59a586fa

On my particular system, there is a time period with a duration of
roughly 11 milliseconds where the device has permissions 600, meaning
that the udev rule (which changes the permissions to 666) has not been
applied yet.

I do not consider this behavior to be a bug, so that's why I'm not
including a lot of details about my specific hardware.  I suspect it
is just part of the design of the kernel or some component of it, and
I'm wondering what a user-mode program should do.

Here are some solutions I considered and why they are not ideal:

1) I suppose I could try to open the devnode, and if there is an
EACCES error I would delay and try again.  This would force me to pick
an arbitrary timeout value to avoid infinite loops.  If the timeout
value is too long, it will be annoying that my program takes so long
to generate a simple "permission denied" error.  If used in a
single-threaded GUI, the delay could make the user interface seem
unresponsive.  If the timeout value is too short, it might not work
reliably on slower systems, such as a Raspberry Pi.  Unfortunately,
this is the best solution I can think of right now.

2) Using stat() to check the permissions of the devnode is not great,
because it does not allow my program to distinguish a device where the
rules have not been applied from a device that does not have the
appropriate rules installed.  That's an important distinction to make
so I can show helpful error messages to the user.  Also, I would have
to make all sorts of assumptions about the permissions/groups of the
process and the desired permissions/groups of the USB devnode for that
to work.  I would rather have my software be more general and not make
those assumptions.

3) I think many of you would suggest that I just use libusb instead of
writing my own low-level code.  However, I was also able to reproduce
this problem using libusb 1.0.20-rc3 and the code below:

https://gist.github.com/DavidEGrayson/282c1d311e9741ff20b4

Occasionally that code will print a LIBUSB_ERROR_ACCESS error when
plugging in the USB device.  The code is constantly creating and
destroying libusb contexts, which is probably important for
reproducing the error because of point 4 below.

4) After a libusb context is created, it looks like libusb detects
changes in the set of USB devices by calling
udev_monitor_receive_device().  The documentation of
udev_monitor_new_from_netlink() says:

> The "udev" events are sent out after udev has finished
> its event processing, all rules have been processed,
> and needed device nodes are created.

Unfortunately, using a udev_monitor (or a libusb context) will make my
code more complicated, because there will be a need to start the
monitor and keep it around while we are waiting for the new USB device
to connect.  It is simpler if I can just ask the system for a list of
all the USB devices and filter out the ones that are not fully set up
yet, without needing to store any context data, or have global
variables, or have a file handle open to the monitor.

Also, if I use the udev_monitor (or a libusb context), I will need to
guarantee that this monitor is started well before the device is
plugged in; if the device is plugged in a little bit before the
monitor is started, then I assume I wouldn't receive an event for the
new device, so I cannot be sure that it is ready to be used.  This
prohibits the useful scenario where process A tells the device to
disconnect from USB (e.g. to go into bootloader mode and appear as a
new USB device), and then we start process B which actually waits for
the new device to appear and then communicates with it. By the time
process B starts, the new USB device may or may not be detected by the
system, so it is too late to start monitoring for it.

5) We've established that the thing sending out udev events knows when
all the rules are done being processed.  I'm wondering if it also
stores that information anywhere so that a user can access it.
Unfortunately, I cannot find that information in any of the entries in
the sysfs path for the USB device (
https://gist.github.com/DavidEGrayson/479d60a1aa037285864b ).

I would appreciate hearing any ideas that you might have about this
problem.  If not, I'll probably just implement a retry/delay/timeout.
Thanks!

--David
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux