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

Writing to an input pin results in permissions errors #167

Closed
rtimmons opened this issue Feb 1, 2020 · 4 comments
Closed

Writing to an input pin results in permissions errors #167

rtimmons opened this issue Feb 1, 2020 · 4 comments

Comments

@rtimmons
Copy link

rtimmons commented Feb 1, 2020

Hi there thank you for your work on this project - it has made my smarthome integration projects significantly easier.

I ran into some trouble earlier with permissions when I mistakenly tried to call write to a pin that I had marked as input:

const pin = new onoff.Gpio(22, 'in');
pin.writeSync(1);
// =>
Error: EPERM: operation not permitted, write
    at Object.writeSync (fs.js:592:3)
    at Gpio.writeSync (/home/pi/node_modules/onoff/onoff.js:243:8) {
  errno: -1,
  syscall: 'write',
  code: 'EPERM'
}

I'm guessing this is due to how raspbian's procfs models input vs output pins.
While this is clearly user-error, the error message was very inscrutible and I wasted more time than I care to admit debugging it 😄

Would you be amenable to me sending a PR that would error out (or warn) if the user tries to call write on a Gpio instance that was marked as input rather than output? I believe this would be a quick change, but I wanted to run it by you prior to spending the time to write and test it.

A "cleaner" solution may be to have distinct GpioInput and GpioOutput that don't have the methods that don't make sense.

const output = new GpioInput(22);
output.readSync(); // works
output.writeSync(1); // method doesn't exist; doesn't compile if using TS

This is obviously a bigger change, but it is something to consider.

Thank you for your time.

@fivdi
Copy link
Owner

fivdi commented Feb 2, 2020

@rtimmons Thank you for filing this issue.

I think there are two issues here.

The first issues is distinguishing between EPERM and EACCES errors on Linux.

EPERM errors occur when an operation is not permitted, for example, because it doesn't make sense or is illogical and typically look something like this:

Error: EPERM: operation not permitted, write

EACCES errors occur when the process doesn't have sufficient privileges to perform the requested operation and typically look something like this:

Error: EACCES, permission denied '/sys/class/gpio/export'

Unfortunately, the distinction between these two errors is quit subtle and it's relatively easy to mistakenly interpret an EPERM error as an EACCES error. I think people will often think that an EPERM error means that they don't have sufficient privileges (permission) to do what they want to do rather than realizing that what they want to do doesn't make sense or is illogical (permitted) from the operating systems perspective. The difficulties in distinguishing between EPERM and EACCES errors is a Linux issue rather that an onoff issue. Mistakenly interpreting an EPERM error as an EACCES error sends people in the wrong direction and results in long and fruitless debugging sessions. This has happened to me more than once in the past.

The second issue is that although it may not make sense to write to an input on a Raspberry Pi it may make sense on other systems. onoff was implemented to work on any Linux system and not only the Raspberry Pi. Whether or not writing to an input makes sense is something that the operating system and device drivers will need to decide. It's not something that I want try to determine in onoff. For example, writing to an input on an AVR microcontroller is a valid operation and is used to enable the pull-up resistor on that input. I realize that this isn't a particularly good example as Linux doesn't run on AVR microcontrollers.

Although your feature request will make sense in 99.9% of cases, I'm afraid that I won't add it to onoff. I want the operating system and device drivers to decide which operations make sense.

@rtimmons
Copy link
Author

rtimmons commented Feb 2, 2020

Thank you for the detailed response, @fivdi. I had never considered the distinction between EPERM and EACCESS in the past - it makes perfect sense in this context. (My original text had been to also suggest forbidding reads from an output pin before I saw your LED example - I should have figured there was a valid reason for the input pins as well.)

While I respect your decision to not work around this, at the very least it would be helpful to point out somewhere, perhaps in method-level documentation, that write failures due to EPERM may be the result of the device not supporting writing to that channel (e.g. it was a rpi pin set to input). This would hopefully save a poor, unfortunate soul some misery trying to sudo chmod -R 777 / 😺. Of course this is up to you - consider me a happy user now that I've figured this out. I would be happy to submit a docs change PR if you think it makes sense.

-Cheers for a good rest of your Sunday-

@fivdi
Copy link
Owner

fivdi commented Feb 2, 2020

it would be helpful to point out somewhere, perhaps in method-level documentation, that write failures due to EPERM may be the result of the device not supporting writing to that channel

Yes, documenting this at method-level for write makes sense.

I would be happy to submit a docs change PR if you think it makes sense.

Yes, that would be great.

@fivdi
Copy link
Owner

fivdi commented Apr 10, 2020

Fixed with c73b473

@fivdi fivdi closed this as completed Apr 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants