JamesBarwell / rpi-gpio.js

Control Raspberry Pi GPIO pins with node.js
MIT License
658 stars 115 forks source link

"export" races udev's resetting of sysfs permissions, causing library to unnecessarily require root. #48

Closed awong-dev closed 7 years ago

awong-dev commented 7 years ago

On Rasbian Jessie, the system comes with a gpio group and udev is configured to change the sysfs permissions such that everything in /sys/class/gpio is writeable by group gpio.

https://github.com/RPi-Distro/raspberrypi-sys-mods/blob/master/etc/udev/rules.d/99-com.rules#L6

In theory, this should allow gpio access for all users in the gpio group without needing root or sudo. However, rpio-gpio seems to consistently get EACCES when attempting to set the edge configuration. It seems what is happening (verified by adding a fs.statSync call as well as watching via strace) is the library is accidentally racing udev's permission reset here:

https://github.com/JamesBarwell/rpi-gpio.js/blob/master/rpi-gpio.js#L183

Furthermore, since the library conservatively unexports the pin if it is exported (https://github.com/JamesBarwell/rpi-gpio.js/blob/master/rpi-gpio.js#L176), it actually causes the race condition to almost always trigger even when the code is executed multiple times.

If at line 183, you add another waterfall stage:

            function(next) {
              setTimeout(next, 5000);  // Just wait 5 seconds.
            }

between the exportPin and setEdge calls, the code will succeed for users in the gpio group w/o requiring root.

Not quite sure what the "right" fix is here, but 2 thoughts: (1) Don't unexport the pin if it's already exported. (2) Use inotify or something and watch for permissions changes to the /sys/class/gpi/gpiXX directory with a timeout before continuing on the waterfall?

awong-dev commented 7 years ago

See https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=100913 and look for by nsayer » Fri Jun 05, 2015 5:21 pm

aztecrex commented 7 years ago

I was tearing my hair out on this one. Eventually found setEdge was failing consistently but no idea why. Glad to have found your post because that's what fixed it for me.

I have submitted a PR that inserts retry logic into setEdge and setDirection. With this patch, I am successfully using the library as non-root.

Thanks for digging into this problem.

aztecrex commented 7 years ago

I have pushed 'rpi-gpio-mod' to npm as a workaround until this or another solution is merged.

JamesBarwell commented 7 years ago

aztecrex's patch was merged in and released as 0.8.1 so hopefully this is now resolved. Cheers.