JamesBarwell / rpi-gpio.js

Control Raspberry Pi GPIO pins with node.js
MIT License
657 stars 116 forks source link

EACCES in setup() caused by race #111

Open smagoun opened 3 years ago

smagoun commented 3 years ago

I'm experiencing intermittent but fairly frequent 'Permission denied' (EACCES) errors in gpio.setup() on my Raspberry Pi Zero W. My program is running as the default 'pi' user on Rasbian 10 (buster). The pi user is a member of the 'gpio' group.

The failure is always the fs.openSync() call in listen(). listen() is called immediately after setDirection(), which makes me think we're hitting the race against udev described here: https://stackoverflow.com/questions/39524234/bug-with-writing-to-file-in-linux-sys-class-gpio

I suspect that the race is more of an issue on slower hardware like the Pi Zero. This small test program usually reproduces the issue for me fairly quickly:

const gpio = require('rpi-gpio');

const PIN_MODE = gpio.MODE_BCM;
const PINS = [2, 3, 4, 14, 15, 17, 18, 27, 22];

function setup() {
    gpio.setMode(PIN_MODE);
    for (const pin of PINS) {
    // This can sometimes thrown an 'EACCES: permission denied' error                                                        
    gpio.setup(pin, gpio.DIR_OUT, function (error) {
            if (error) {
        console.log('Setup error:', error);
        process.exit();
            } else {
        console.log('Setup pin', pin);
            }
    });
    }
}

setup();

Output:

pi@raspberrypi:~/testgpio $ node testgpio.js
Setup pin 2
Setup pin 3
Setup pin 15
Setup pin 4
Setup pin 14
Setup pin 17
Setup pin 27
Setup error: Error: EACCES: permission denied, open '/sys/class/gpio/gpio18/value'
    at Object.openSync (fs.js:476:3)
    at listen (/home/pi/testgpio/node_modules/rpi-gpio/rpi-gpio.js:430:21)
    at /home/pi/testgpio/node_modules/rpi-gpio/rpi-gpio.js:248:3 {
  errno: -13,
  syscall: 'open',
  code: 'EACCES',
  path: '/sys/class/gpio/gpio18/value'
}

Adding retry logic to the call to listen works around the problem for me. I'll put up a PR with my fix.