Looking around to avoid running aprogram as root to access the GPIO ports, I notice the devices were all group gpio (and the default pi user in raspbian Jessie is also a member of group gpio), so I made my app run as a user with supplementary group gpio.
It nearly worked, except I was getting EACCESS trying to open the direction device node at initialisation after exporting the GPIO port. This was a bit puzzling as it seemed to work if I tried it by hand.
Anyway, to cut a long story short, it seems you have to wait a bit after exporting a GPIO pin before you can open the direction device node using your group access (as opposed to being root, where it works without delay). I ended up including some logic which retries after a 20ms delay iff the open returns EACCESS, and I do this up to 50 times (i.e. trying for 1 second) before giving up. Typically, it takes between 80ms and 300ms before the open will work. Also, it only seems to affect the first direction device node I open - subsequent direction device node opens for other GPIO ports open instantly, but this might be because I do all the exports, and then all the direction settings. If interleaved, it might be that the delay would be needed for every port, although I haven't tried this.
The error might happen on any access to the port, but in my app, it so happens that the direction device nodes are the first ones I use after exporting the GPIO port, so that's what gets hit.
This race condition is probably a bug in the filesystem device node code (devices are not fully setup to use when the port export write returns), but at least some understanding of it allows you to easily workaround it.
Thought this might be useful to anyone else trying to drive the GPIO pins from a non-root user and getting EACCESS.