When working with sysfs GPIO on Linux, you are instructed to poll for POLLPRI and POLLERR events.
This is quite easy:
poll = select.poll()
poll.register(filename, select.POLLPRI | select.POLLERR)
result = poll.poll(timeout=timeout)
However, I would like to write tests for this code, and simulation tests for the application relying on it. So, I need to be able to cause a POLLPRI event.
I have tried using a Unix domain socket, but then I am unable to open the file for reading after the domain socket has connected (errno 6, no such device). I also tried using a socket with SOCK_DGRAM, but that either fails to find the file if not already created, or yields connection refused.
I want a way to open a regular file or create a file that can be opened like a regular file and be able to send it a stream of messages that are treated as "urgent data". ie MSG_OOB.
What can I do?
It looks like you can achieve this by polling a sysctl exposed in procfs. If you look at the poll implementation in procfs for the sys subdirectory, you'll see that any sysctl that implements notifications for poll will return a mask that includes POLLERR|POLLPRI. So how do we figure out what sysctls implement this? We look for uses of proc_sys_poll_notify!
One such place is in proc_do_uts_string, which implements a number of sysctls under /proc/sys/kernel. Most of these are read-only, but hostname and domainname can be written (see also their table entries).
Of course, this is going to require root privileges to be able to write to e.g. /proc/sys/kernel/hostname.
This is probably the easiest way to do such a thing while staying within a synthetic filesystem implementation. Of course, the only real way to test your code is to poll(2) one of your pins, press a button, and see if you get your rising / falling signal interrupts.
Note: sysfs also does this for edge nodes in the tree:
>>> import select
>>> f = open('/sys/bus/clockevents/devices/clockevent0/uevent', 'r')
>>> p = select.poll()
>>> p.register(f, select.POLLPRI | select.POLLERR)
>>> result = p.poll(10)
>>> result
[(3, 10)]
10 is of course POLLPRI (0x2) | POLLERR (0x8). I got the same results using /sys/power/state as my input. Basically, if you poll any user-readable, non-directory file entry in sysfs, you'll get POLLPRI | POLLERR back.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With