joan2937 / lg

Linux C libraries and Python modules for manipulating GPIO
The Unlicense
57 stars 20 forks source link

Consider different/configurable name and location for .lgd-nfyx pipes #12

Open matthijskooijman opened 2 years ago

matthijskooijman commented 2 years ago

Currently, lg seems to create pipes named .gld-nfy<handle> in the current directory (where I believe handle is just an index of opened handles inside the current process). This approach has two problems:

  1. It assumes that the current directory is writable, which might not always be the case (I'm running into this issue with a read-only rootfs, where only places like /run, /var/tmp and /tmp are writable).
  2. If multiple processes using lgpio are started in the same directory, they will overwrite each others pipes (this is hypothetical based on looking at the code, I have not actually tried this).

Maybe it would be good to revisit the naming to fix either or both of these?

For 1., I would suggest using /run/user/<uid> to create these pipes. This seems to be the standard location on modern Linux distros, as defined by the FHS (See for example https://renenyffenegger.ch/notes/Linux/fhs/run/user/uid/index). Rather than hardcoding just this location, I guess it would be good to make it configurable, and also provide fallbacks. I can imagine to use the first of the following that is writable: $LG_RUNTIME_DIR, $XDG_RUNTIME_DIR, /run/user/<pid>, '/tmp/,.(I'm not sure about/tmp`, using that might be a security risk).

For 2., I would suggest maybe using something like .gld-nfy-<pid>-<handle>, which should make the filenames unique.

However, while writing this, I wonder if it would not be possible to simply use a anonymous socketpair (see https://man7.org/linux/man-pages/man2/socketpair.2.html) rather than an on-disk fifo. IIRC this supports pretty much the same thing (bidirectional data transfer using read()/write(), but does not need to be stored on disk (you would just need a way to return the FD to the calling program, rather than just the handle). I do not have a full picture of the architecture involved, so it's likely that I'm missing some part that prevents this, but maybe you just haven't considered this option?

joan2937 commented 2 years ago

All good points. I wasn't happy having the pipes in the local directory. Unfortunately I do not remember my thinking at the time. I think point 2) is handled by Linux as I certainly had multiple non-conflicting processes during testing.

I like your suggestions. I will look into this again but can not give a time-scale. If you have a working solution I will happily accept a pull request.

matthijskooijman commented 2 years ago

All good points. I wasn't happy having the pipes in the local directory. Unfortunately I do not remember my thinking at the time. I think point 2) is handled by Linux as I certainly had multiple non-conflicting processes during testing.

Thanks. I recently needed something like this for another project and found that the default anonymous pipes were cumbersome, since they are unidirectional (so you'd need two, and thus juggle 4 fd's...). Then I found that a socketpair (of the unix stream type) can do pretty much the same, but bidrectional.

I like your suggestions. I will look into this again but can not give a time-scale. If you have a working solution I will happily accept a pull request.

Cool! I would love to make a pull request, but the meadow for this project already has a big herd of yaks, so I cannot really spare the time...

joan2937 commented 2 years ago

I suggest unless I can think of a better solution you will need to set the working directory when your programs start.

The daemon rgpiod has the -w option.

The other programs will pick up their working directory from the LG_WD environment variable. E.g.

export LG_WD=/tmp