Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux hidraw: Occasional 'permission denied' when opening device #217

Open
mrpippy opened this issue Apr 1, 2015 · 2 comments
Open

Linux hidraw: Occasional 'permission denied' when opening device #217

mrpippy opened this issue Apr 1, 2015 · 2 comments

Comments

@mrpippy
Copy link
Contributor

mrpippy commented Apr 1, 2015

My app runs hid_enumerate() every 500 ms, and calls hid_open() when a new device is enumerated.

About 1 out of 10 times, hid_open() fails in hid_open_path(), because open() fails with permission denied

It looks like this is a race condition, trying to open /dev/hidraw0 before udev has properly set permissions on it. I put in a system() call to do ls -l <path> after open() fails, and this was the result:

hid_open_path() open() /dev/hidraw0 failed: Permission denied
crw------- 1 root root 248, 0 Apr  1 11:59 /dev/hidraw0

And even that result was not consistent, for several failures ls showed the correct final permissions.

Is there any solution to this, other than putting a few hundred ms delay in between hid_enumerate() and hid_open()?

udev rule (in /etc/udev/rules.d)
ATTRS{idVendor}=="2057", ATTRS{idProduct}=="0001",MODE="0666"

Ubuntu 14.04 32-bit running kernel 3.13.0-48-generic

@amullins83
Copy link
Contributor

Does it only happen when enumerating twice per second? Does the percentage of failure depend on the delay between successive enumerations? In other words, if you extend the delay to 1s, does it fail 1 out of 20 times or is it still 1 out of 10? I'm thinking there should be a way to subscribe to udev events instead of constantly calling hid_enumerate. It would ideally involve a new API function, but hardware events are really different between operating systems.

@mrpippy
Copy link
Contributor Author

mrpippy commented Apr 7, 2015

With the delay at 1 second the failure percentage goes way down. But with the delay at 100 ms, it happened more often than at 500 ms.

Here's what I think is happening:

udev         | --- device detect ------------------------------------------------- set permissions on device node ----- |
hidapi/app   | ---------------------- hid_enumerate() ------- hid_open() fails ------------- |

I think it fails more often when hid_enumerate() is called more often, just because it increases the probability of hid_enumerate() getting called in that small window.

The root issue I see is that a device can be enumerated before the device node is actually ready to be opened. I see a libudev function called udev_device_get_is_initialized() which is described as
Check if udev has already handled the device and has set up device node permissions and context

I added a check with this call into hid_enumerate() and sure enough, as long as it returns 1 (device initialized), hid_open() never fails. I'll open a pull request for this tomorrow.

mrpippy pushed a commit to mrpippy/hidapi that referenced this issue Apr 8, 2015
…() returns it

In hid_enumerate(), skip any devices which have not yet been initialized by udev (which includes setting permissions on the device node).
Previously, a race condition was possible where hid_enumerate() could return a device that hid_open() could not open, because udev had not set permissions on the device node yet.

This resolves issue 217, "Occasional 'permission denied' when opening device" (signal11#217)
mrpippy pushed a commit to mrpippy/hidapi that referenced this issue Apr 8, 2015
… returns it

In hid_enumerate(), skip any devices which have not yet been initialized by udev (which includes setting permissions on the device node).
Previously, a race condition was possible where hid_enumerate() could return a device that hid_open() could not open, because udev had not set permissions on the device node yet.

This resolves issue 217, "Occasional 'permission denied' when opening device" (signal11#217)
mrpippy added a commit to mrpippy/hidapi that referenced this issue Apr 8, 2015
… returns it

In hid_enumerate(), skip any devices which have not yet been initialized by udev (which includes setting permissions on the device node).
Previously, a race condition was possible where hid_enumerate() could return a device that hid_open() could not open, because udev had not set permissions on the device node yet.

This resolves issue 217, "Occasional 'permission denied' when opening device" (signal11#217)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants