This question already has an answer here:

Here's the code:

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char** argv) {
  char buf[1024];
  int fd = open("/sys/class/gpio/export", O_WRONLY);
  if (fd < 0) { perror("1"); exit(1); }
  write(fd, "8", 2);
/* workaround is to put sleep(2); here */
  fd = open("/sys/class/gpio/gpio8/direction", O_RDONLY);
  if (fd < 0) { perror("2"); exit(1); }
  printf("reading: ");
  int c;
  while((c = read(fd, buf, sizeof(buf))) > 0)
    write(fileno(stdout), buf, c);
  fd = open("/sys/class/gpio/gpio8/direction", O_WRONLY);
  if (fd < 0) { perror("3"); exit(1); }
  write(fd, "out", 4);

The user running it is a member of group gpio.

If you start with gpio8 unexported, this code will print "reading: out" and then "3: Permission Denied." If you immediately run it a second time, it will print "reading: out" and nothing else.

I don't see how this is anything other than a bug in sysfs.

Note that according to the man page for open(2), EPERM isn't even the correct error for an access control failure. That would be EACCESS. EPERM is reserved for opens with O_NOATIME, which isn't the case here.


Adding the commented-out workaround "solves" the problem. So this looks even more like a bug now.

marked as duplicate by goldilocks Jun 5 '15 at 9:18

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Oh, and thanks to raspberrypi.stackexchange.com/questions/23162/… for pointing out the workaround. – nsayer Jun 5 '15 at 4:14
  • 1
    Does the write "8" work? You have not checked. Why not "8\n"? – joan Jun 5 '15 at 7:48
  • 1
    As per the answer on S.O. from the other question, this has to do with a udev based mechanism installed by default on (newer version of) Raspbian. See grep gpio /lib/udev/rules.d/*. I think you still had to do/install something to change the permissions on /sys/class/gpio/export, since otherwise this code would not work from the get-go. WRT the work-around, I would try busy looping on the open(O_WRONLY) call. May be worse, may be better. – goldilocks Jun 5 '15 at 9:18
  • I agree with the mark-as-duplicate action. I didn't know that at the time, but it's absolutely a udev race condition. – nsayer Jul 19 '15 at 23:06

Browse other questions tagged or ask your own question.