rust-embedded/rust-sysfs-gpio

Pin can be exported twice

dbrgn opened this issue · 4 comments

dbrgn commented

I'm using the following code:

fn open_door(gpio_pin: u64) -> GpioResult<()> {
    let pin = Pin::new(gpio_pin);
    pin.with_exported(|| {
        try!(pin.set_direction(Direction::Out));
        try!(pin.set_value(1));
        sleep(Duration::from_secs(OPEN_SECONDS));
        try!(pin.set_value(0));
        Ok(())
    })
}

If I run this program twice in parallel, the pin is exported without errors, but the second unexport fails:

Opening door on GPIO 17 for 5 seconds...
Opening failed: Io(Error { repr: Os { code: 2, message: "No such file or directory" } })

Can this be handled somehow?

Yeah, since the export operation is mutated system-level state (i.e. in the kernel), it is probably best to pick one spot to export the pin, typically in an early init script. I recently published this for just that purpose: https://github.com/rust-embedded/gpio-utils. There you can associate names and use the new https://github.com/rust-embedded/rust-sysfs-gpio/blob/master/src/lib.rs#L151 to open the pin from the symlink location.

Alternatively, it may make sense for your process to just export the required pins where needed without unexporting. The export call intentionally does not fail if the pin is already exported.

Another option would be to create the Pin at a higher level and put a Mutex around it so threads have exclusive access. This is not required in the general case, so this library does not seek to do that for you.

dbrgn commented

Another option would be to create the Pin at a higher level and put a Mutex around it so threads have exclusive access.

That works for multiple threads, but not for multiple processes :)

Maybe it would be possible to add a flag to ignore unexport errors if the reason is a "file not found" error (meaning that the pin was already unexported)? Or maybe even as a default option? Exporting an already exported pin doesn't result in an error either.

Maybe it would be possible to add a flag to ignore unexport errors if the reason is a "file not found" error (meaning that the pin was already unexported)? Or maybe even as a default option? Exporting an already exported pin doesn't result in an error either.

You are welcome to do this in your own code that does something similar to with_exported but I don't think it makes sense to add additional options to what exists. Generally, I only see a need to export pins once per system boot if they are going to be used by userspace programs.